Redis 实现限流策略

除了控制流量,限流还有一个应用目的是用于控制用户行为,避免垃圾请求。

比如在 UGC 社区,用户的发帖、回复、点赞等行为都要严格受控,一般要严格限定某行为在规定 时间内允许的次数,超过了次数那就是非法行为。对非法行为,业务必须规定适当的惩处策略。

一、简介

throttle意为限流阀,Redis4.0 开始提供了一个 Redis-Cell 模块,这个模块使用漏斗算法,提供了一个非常好用的限流指令。漏斗算法就像名字一样,是一个漏斗,请求从漏斗的大口进,然后从小口出进入到系统中,这样,无论是多大的访问量,最终进入到系统中的请求,都是固定的。

二、安装

wget https://github.com/brandur/redis-cell/releases/download/v0.2.4/redis-cell- v0.2.4-x86_64-unknown-linux-gnu.tar.gz 
tar -zxvf redis-cell-v0.2.4-x86_64-unknown-linux-gnu.tar.gz 
mkdir redis-cell 
mv libredis_cell.d ./redis-cell 
mv libredis_cell.so ./redis-cell
 
接下来修改 redis.conf 文件,加载额外的模块:
loadmodule /root/redis-5.0.7/redis-cell/libredis_cell.so
 
然后,启动 Redis:
redis-server redis.conf
 

9125829fc220250412112254

 

redis 启动成功后,如果存在 CL.THROTTLE 命令,说明 Redis-Cell 模块已经安装成功了。该模块只有 1 条指令 cl.throttle,它的参数和返回值都略显复杂,接下来让我们来看看这 个指令具体该如何使用。,支持分布式。
 
CL.THROTTLE 命令一共有五个参数
第一个参数是 key
第二个参数是令牌桶容量
令牌产生个数
令牌产生时间
本次取走的令牌数
 
执行完成后,返回值也有五个:
第一个 0 表示允许,1表示拒绝
第二个参数是令牌桶的容量
第三个参数是当前桶内剩余的令牌数
失败时表还需要等待多少秒可以有足够的令牌
表预计多少秒后令牌桶会满
 
dfd8809aea20250412110707

上面这个指令的意思是允许「用户老钱回复行为」的频率为每 60s 最多 30 次(漏水速 率),漏斗的初始容量为 16,也就是说一开始可以连续回复 16 个帖子,然后才开始受漏水速率的影响。我们看到这个指令中漏水速率变成了 2 个参数,替代了之前的单个浮点数。用 两个参数相除的结果来表达漏水速率相对单个浮点数要更加直观一些。 

  • > cl.throttle laoqian:reply 15 30 60
  • 1) (integer) 0 # 0 表示允许,1 表示拒绝
  • 2) (integer) 15 # 漏斗容量 capacity
  • 3) (integer) 14 # 漏斗剩余空间 left_quota
  • 4) (integer) -1 # 如果拒绝了,需要多长时间后再试(漏斗有空间了,单位秒)
  • 5) (integer) 2 # 多长时间后,漏斗完全空出来(left_quota==capacity,单位秒)

在执行限流指令时,如果被拒绝了,就需要丢弃或重试。cl.throttle 指令考虑的非常周 到,连重试时间都帮你算好了,直接取返回结果数组的第四个值进行 sleep 即可,如果不想 阻塞线程,也可以异步定时任务来重试。

 
 
cl.throttle laoqian:reply 10 10 60 1

可以与上面漏桶算法做个对比,

第一个参数 laoqian:reply #key

第二个参数 10 #漏斗容量

第三、四个参数 10 60 #每60秒10次操作

第五个参数 1 #每次进入漏斗的量(可选参数,默认为1)

返回结果

1)(integer) 0 #0表示允许,1表示拒绝

2)(integer)10 #漏斗容量

3)(integer)9 #漏斗剩余空间

4)(integer)-1 #如果被拒绝了,需要多长时间再试(漏斗有空间了,单位秒)

5)(integer)6 #多长时间后,漏斗完全空出来

如果被拒绝了,就需要丢弃或重试,直接取出返回结果的第四个值进行sleep即可,如果不想阻塞线程,也可以异步定时任务来重试。

© 版权声明
THE END
喜欢就支持一下吧
点赞9赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容