为了保证服务在高峰时期,业务系统能稳定执行,并有一定的弹性。需要提供降级及熔错功能。
1. 限流
通过对并发访问/请求进行限速或一个时间窗口内的请求进行限速,从而达到保护系统的目的。
一般系统可以通过压测来预估能处理的峰值,一旦达到设定的峰值阀值,则可以拒绝服务(定向错误页或告知资源没有了)、排队或等待(例如:秒杀、评论、下单)、降级(返回默认数据)。
常用限流算法:
Leaky bucket
Token bucket
Fixed window counter
Sliding window log
Sliding window counter
Leaky bucket:
漏桶算法,强行限定请求速率,当请求过大会直接溢出,不能应对突发流量。
leakyBucket.png
Token bucket:
令牌桶算法,允许突发请求,有一定的弹性。
leakyBucket.png
Fixed window counter:
固定时间窗口,单个间段都符合限制频率,但连续的时间段超过限制频率
fixedWindowCounter.png
Sliding window:
滑动时间窗口
slidingWindow.png
针对单应用,Google guava 类库里已经提供了漏桶及令牌桶算法
分布式的情况下,用滑动窗口是最合理的。
用 redis + lua来实现。
local key = KEYS[1]
local now = tonumber(ARGV[1])
local windowInSecond = 1
local limit = 50
local clearBefore = now - windowInSecond * 1000
redis.call("ZREMRANGEBYSCORE", key, 0, clearBefore)
local amount = redis.call("ZCARD", key)
if amount < limit then
redis.call("ZADD", key, now, now)
end
redis.call("EXPIRE", key, windowInSecond)
local remaining = math.max(0, limit - amount)
return remaining
网友评论