redis+lua实现滑动窗口限流

前言

关于滑动时间窗口算法以及更多限流实践请走:接口限流实践

脚本

主要是利用redis的有序集合(zset)来实现,计算前一秒内已访问的次数主要使用zcount命令来计算在当前集合中指定区间分数内的成员数,如果不使用lua脚本,各命令调用之间会存在并发隐患,而redis会将整个lua脚本作为一个命令执行,保证原子操作,无需担心并发,我们可以将所有计算逻辑均放在脚本内,脚本如下:

local key = KEYS[1]
-- 一个时间窗口限制数量
local limitCount = tonumber(ARGV[1])
-- 获取当前时间,单位毫秒
local currentTime = tonumber(ARGV[2])
-- 当前时间戳的key值,唯一
local timeKey = ARGV[3]
-- 获取时间窗口范围,传参单位秒,默认窗口一秒
local timeRange
if ARGV[4] == nil then
	timeRange = 1000
else
	timeRange = tonumber(ARGV[4]) * 1000
end
-- 获取集合key过期时间,当key过期时会存在瞬时并发的情况,因此过期时间不能太短或者改用定时清除,传参单位秒,默认一小时
local expiration
if ARGV[5] == nil then
	expiration = 3600
else
	timeRange = tonumber(ARGV[5])
end
-- 前一秒内已访问的次数
local beforeCount = 0
local existKey = redis.call('exists', key)
if (existKey == 1) then
	-- 计算前一秒访问次数
	beforeCount = redis.call('zcount', key, currentTime - timeRange, currentTime)
end
-- 记录当前访问时间
redis.call('zadd', key, currentTime, timeKey)
local result = 0
if (limitCount > beforeCount) then
	result = 1
end
-- 设置过期时间
redis.call('expire', key, expiration)
return result

需要注意的是,有序集合中的key必须保持唯一,不能采用时间戳

猜你喜欢

转载自blog.csdn.net/m0_38001814/article/details/113643374