限流
-
定时清除 (1分钟一清除)
- 实现简单
- 对于边界值,如59秒和下一秒会有问题,会得到一个请求限制速率的2倍
-
滑动窗口(10秒一清除)
- 是定时清除的一个优化,缩小了清除粒度但是还是有问题。
-
漏桶算法 (桶容量 + 桶流速度) https://github.com/uber-go/ratelimit
- 超过桶的容量就要涉及到排队或拒绝了
- 不支持小流量激增
-
令牌桶算法(定时放入桶中令牌) https://github.com/juju/ratelimit
- 支持小流量并发激增
分布式限流则可用于 Redis + Lua脚本实现,其原理几乎差不多。
local key = "rate.limit:" .. KEYS[1] --限流KEY
local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
return 0
else --请求数+1,并设置1秒过期
redis.call("INCRBY", key,"1")
redis.call("expire", key,"1")
return current + 1
end
再用相应的语言调用脚本。
- Java代码传入key和最大的限制limit参数进lua脚本
- 执行lua脚本(lua脚本判断当前key是否超过了最大限制limit)
-
- 如果超过,则返回0(限流)
- 如果没超过,返回1(程序继续执行)