上一篇文章限流技术总结中,我们说到传统的限流算法只能实现单机的限流,如果要实现分布式限流,可以考虑借助redis来实现限流算法。
这篇文章我们就来实现这个基于redis的分布式限流方案。
为什么要选用redis:
- redis效率高,易扩展
- redis对语言无关,可以更好的接入不同语言开发的系统(异构)
- redis单进程单线程的特点可以更好的解决最终一致性,多进程间协同控制更为容易
计数器算法实现
先来看一个比较简单的计数器算法的实现。
计数器算法前文限流技术总结有过详细说明,现在我们用lua代码来实现这个算法:
1 | -- 资源唯一标识 |
令牌桶算法
计数器算法容易出现不平滑的情况,瞬间的qps有可能超过系统的承载。因此在实际场景中我们一般很少使用。
令牌桶算法是一个比较常用的限流算法,也是Guava中使用的算法。我们使用lua来实现令牌桶算法:
1 | -- key |
- 如果是
acquire
方法,则执行:
1 | eval 'lua脚本' 3 '自定义的key' '最大存储的令牌数' '每秒钟产生的令牌数' '请求的令牌数' |
redis将返回获取请求成功后,线程需要等待的微秒数
- 如果是
tryAcquire
方法,则执行:
1 | eval 'lua脚本' 3 '自定义的key' '最大存储的令牌数' '每秒钟产生的令牌数' '请求的令牌数' '最大等待的微秒数' |
redis同样返回需要等待的微秒数,将该返回值与最大等待微秒数做比较,如果redis返回的值较大,则说明失败;反之则是成功,并根据返回值让线程等待。
完整代码请参考:https://github.com/wangqifox/redis-limiter
http://tech.dianwoda.com/2017/09/11/talk-about-rate-limit/
https://www.zybuluo.com/kay2/note/949160
https://segmentfault.com/a/1190000012947169