使用 sorted set 实现令牌桶限流
-- sorted set 令牌桶的 key
local key = KEYS[1];
-- 当前日期 格式为 yyyy-MM-dd
local member = ARGV[1];
-- 当前日期 0 点对应的时间戳 单位为秒
local timestamp = tonumber(ARGV[2]);
local exists = redis.call('exists', key);
if exists == 0 then
-- 创建并授权
redis.call('zadd', key, timestamp, member);
redis.call('expire', key, 7 * 24 * 60 * 60);
return 1;
else
-- 移除七天前的授权记录 本质是回收令牌
local sevenDaysAgo = timestamp - 7 * 24 * 60 * 60;
redis.call('zremrangebyscore', key, '-inf', sevenDaysAgo);
-- 如果队列长度少于 3 则尝试进行授权
local length = redis.call('zcard', key);
if length < 3 then
local count = redis.call('zcount', key, timestamp, timestamp);
if (count == 0) then
-- 每天不超过一次
redis.call('zadd', key, timestamp, member);
redis.call('expire', key, 7 * 24 * 60 * 60);
return 1;
else
return 0;
end;
else
return 0;
end;
end;