限流
一个通用的限流接口就是一个用户只能在特定的时期内对于特定的行为只允许发生有限次。
可以简单的用redis的zset来实现这个功能,zset中的score就代表时间,用户每发起一次请求都维护一次zset,清理掉多余的任务,这里的value只需要保证唯一即可,所以选用毫秒时间戳。但是这个简单的限流功能不适合巨大的数据量,因为要保存所有的行为记录很耗费空间。
另一种简单的限流方案就是用redis里的基础key-value,value设置为访问次数,超过一定次数就拒绝访问,时间用key的过期时间来控制。这种方案简单但是很粗糙。
自己难以实现分布式算法,虽然限流漏斗算法的关键值可以存在redis中,但是却无法保证原子性,加锁失败又会导致等待或放弃。
漏斗算法
redis内置有一个redis-cell模块使用了漏斗算法:
cl.throttle 键 a b c d
a是漏斗的初始容量(刚开始可以一口气执行这些操作)
b/c代表漏水速率(每c秒可以执行b次)
d代表可选参数
执行后返回值有漏斗容量、剩余空间、拒绝后重试的时间、多久后漏斗完全空出。
如果失败了直接取返回的重试时间sleep即可,也可以用异步定时任务。