分布式限流
分布式限流最关键的是要将限流服务做成原子化,而解决方案可以使用Redis+Lua或者Nginx+Lua技术来实现。
限制某个接口的时间窗请求数
Redis+Lua实现
我们需要编写一个Lua脚本:
-- 限流脚本
local key = KEY[1] -- 限流KEY(1秒1个)
local limite = tonumber(ARGV[1]) -- 限流大小
local current = tonumber(redis.call("INCRBY",key, "1")) -- 请求数加1
if current > limite then
return 0
elseif current == 1 then
redis.call("EXPIRE", key, "2")
end
return 1
脚本说明(Lua小白必备)
①在Lua脚本中执行Redis命令:redis.call()
②
tonumber
是Lua的一个函数,这个函数会尝试将它的参数转换为数字③ARGV[1]表示传递给脚本的第一个参数的值
因为如上操作是在一个Lua脚本中,且Redis是单线程模型,因此是线程安全的。 但是上面的脚本有一个问题:当达到限流大小后还是会递增,可以进行如下改造:
-- 限流脚本
local key = KEY[1] -- 限流KEY(1秒1个)
local limite = tonumber(ARGV[1]) -- 限流大小
local current = tonumber(redis.call("GET",key) or "0") -- 之前请求数
if current + 1 > limite then
return 0
else -- 请求数加1,并设置2秒过期
redis.call("INCRBY", key, "1")
redis.call("EXPIRE", key, "2")
return 1
end