现在系统中由于各种需要,经常遇到一种场景:需要限定每个IP地址每分钟最大访问次数类似的需求。下面是使用Redis实现范文频率限制的一种方式。
场景:要限制每分钟每个用户最多只能访问100个页面。
思路:1. 对每个用户使用一个名为“rate.limiting:用户IP”的字符串类型键;
2. 每次用户访问,使用INCR命令递增该键的键值
3. 如果递增后的值是1(第一次访问页面),则同时还要设置该键的生存时间为1分钟
4. 这样每次访问页面时都读取该键的键值,如果超过了100就表明该用户的访问频率超过了限制
PS:该键每分钟会自动被删除,所以下一分钟用户的访问次数又会重新计算,这样就达到了限制访问频率的目的。
上述流程的伪代码如下:
$isKeyExists = EXISTS rate.limiting:$IP if $isKeyExists is 1 $times = INCR rate.limiting:$IP if $times > 100 print 访问频率超过了限制,请稍后再试 exit else INCR rate.limiting:$IP EXPIRE $keyName, 60
上面的这段代码存在一个不太明显的问题:加入程序执行完倒数第二行后,因为某种原因突然退出了,没能够为该键值设置生存时间,那么该键会永久存在,导致使用对应IP的用户最多只能访问系统100次,除非管理员手动删除该键。这是一个很严重的问题,但是可以结合Redis的事务功能解决该问题,修改后的伪代码如下:
$isKeyExists = EXISTS rate.limiting:$IP if $isKeyExists is 1 $times = INCR rate.limiting:$IP if $times > 100 elsee EXPIRE $keyName, 60 EXEC
访问频率限制到此基本上已经实现,但是仍然有细节地方可以改进。
场景:一个用户在1分钟的第1秒访问了1次系统,在同一分钟的最后1秒访问了99次;又在下一分钟的第一秒访问了100次系统,这种情况用户实际上在2秒内访问了199次系统,这与每个用户每分钟只能访问100次的限制的差距较大。
尽管这种情况比较极端,但是在一些场合中还是需要粒度更小的控制方案。
问题解决思路:如果要精确的保证每分钟最多访问100次,需要记录下每次访问的时间。因此对每个用户,我们使用一个列表类型的键来记录他最近100次访问时间,一旦键中的元素超过100个,就判断时间最早的元素距离现在的时间是否小于1分钟。如果是则表示最近1分钟内的访问次数超过了100次;如果不是就讲现在的时间加入到列表中,同时把最早的元素删除。
上述流程的伪代码如下:
$listLength = LLEN rate.limiting:$IP if $listLength < 100 LPUSH rate.limiting:$IP, now() else $time = LINDEX rate.limiting:$IP, -1 if now() - $time < 60 print 访问频率超过了限制,请稍后再试 else LPUSH rate.limiting:$IP, now() LTRIM rate.limiting:$IP, 0, 99
上述代码中用now()函数获得当前的Unix时间。由于需要记录每次访问的时间,所以当要限制“单位时间最多访问N次” 时,如果N的数值越大,此方法占用的存储空间就越多,实际使用时还需要开发者自己去权衡。除此之外,该方法也会出现竞态条件,使用时请注意。
相关推荐
redis实现简单排行榜,和消息处理。
Spring Boot 使用 AOP 和 Redis 实现接口限流是一种高效且实用的方法,用于控制对特定接口的访问频率。以下是实现这个功能的基本步骤: 引入依赖:首先,在 Spring Boot 项目中引入 Redis 和 AOP 的相关依赖。这...
tomcat-redis实现session共享
Qt 使用 Redis实现 消息队列,点对点 生产者-消费者 模式
今天用了一天来搞定了ssm+redis集成和nginx实现负载均衡,这里只有ssm+redis简单d集成demo,希望大家一起来讨论
Redis开发基于redis实现高并发异步秒杀点评项目.zipRedis开发基于redis实现高并发异步秒杀点评项目.zipRedis开发基于redis实现高并发异步秒杀点评项目.zipRedis开发基于redis实现高并发异步秒杀点评项目.zipRedis...
基于mq和redis实现的秒杀系统基于mq和redis实现的秒杀系统
主要介绍了Java基于redis实现分布式锁代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
本篇文章主要介绍了基于 Redis 实现分布式应用限流的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
redis实现分布式锁,自旋式加锁,lua原子性解锁
springboot+websocket+redis实现聊天室功能,可以实现私聊和群聊(并支持发送图片)
shiro+spring+data+session+redis实现单点登录,这是一个不错的案例,学习和参考都是很不错的
redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现 redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现
基于SSM框架+Redis实现的线上秒杀系统项目源码 基于SSM框架+Redis实现的线上秒杀系统项目源码 基于SSM框架+Redis实现的线上秒杀系统项目源码 基于SSM框架+Redis实现的线上秒杀系统项目源码 基于SSM框架+Redis实现的...
保证能跑通-基于Redis Zset实现排行榜功能的源码,包含页面,接口,下载运行即可访问,步骤请阅读README.MD文件
基于Redis实现的简单消息队列。针对队列事务一致性等要求不高的情况下,也可以使用Redis消息队列实现服务间的通讯
通过本代码,可以搭建springboot + redis实现session共享。利用redis特性可以进行分布式session共享。
springboot+redis实现查询附近商铺功能.zip
基于redis实现tomcats ession共享与集群
利用Nginx进行分布式部署,并使用redis实现session共享,https://blog.csdn.net/qq_34742298/article/details/80857173