前提
redis+lua
滑动窗口
-- 滑动窗口 local key = KEYS[1] local maxSize = ARGV[1] local currentTime = ARGV[2] local startTime = ARGV[3] local uuid = ARGV[4] local currentCount = redis.call('zcount',key,startTime,currentTime) if (currentCount and tonumber(currentCount)>=tonumber(maxSize)) then return 0 end -- 防止zset添加同一时间添加元素覆盖,添加后缀uuid redis.call('zadd',key,currentTime,currentTime..uuid) redis.call('expire',key,60*60*24) -- 删除过期时间区间 redis.call('zremrangebyscore',key,0,startTime-10000) return 1
漏桶
-- 漏桶 -- capacity:容量,passRate:漏水速率,addWater:每次请求加水量(默认为1),water:当前水量,lastTs:时间戳 local limitInfo = redis.call('hmget',KEYS[1],'capacity','passRate','water','lastTs') local capacity = limitInfo[1] local passRate = limitInfo[2] local water = limitInfo[3] local lastTs = limitInfo[4] local addWater = 1 -- 初始化漏桶 if capacity == false or passRate==false then capacity = tonumber(ARGV[1]) passRate = tonumber(ARGV[2]) water = addWater lastTs = ARGV[3] redis.call('hmset',KEYS[1],'capacity',capacity,'passRate',passRate,'addWater',addWater,'water',water,'lastTs',lastTs) return 1 else local nowTs = ARGV[3] -- 当前距离上一次漏水量 local waterPass = tonumber((tonumber(nowTs)-tonumber(lastTs))*tonumber(passRate)/1000) water = math.max(0,tonumber(water-waterPass)) lastTs = nowTs if capacity-water>=addWater then water = water+addWater capacity = tonumber(ARGV[1]) passRate = tonumber(ARGV[2]) redis.call('hmset',KEYS[1],'capacity',capacity,'passRate',passRate,'water',water,'lastTs',lastTs) redis.call('expire',KEYS[1],60*60*24) return 1 end return 0 end
令牌桶
-- 令牌桶 -- capacity:容量,rate:令牌生成速率,leftTokenNum:剩余令牌数,lastTs:时间戳 local limitInfo = redis.call('hmget',KEYS[1],'capacity','rate','leftTokenNum','lastTs') local capacity = limitInfo[1] local rate = limitInfo[2] local leftTokenNum = limitInfo[3] local lastTs = limitInfo[4] -- 本次需要的令牌数 local need = 1 if capacity==false or rate==false or leftTokenNum==false then capacity = tonumber(ARGV[1]) rate = tonumber(ARGV[2]) lastTs = ARGV[3] leftTokenNum = capacity-need redis.call('hmset',KEYS[1],'capacity',capacity,'rate',rate,'leftTokenNum',leftTokenNum,'lastTs',lastTs) return 1 else local nowTs = ARGV[3] -- 距离上次产生的令牌数 local createTokenNum = tonumber((tonumber(nowTs)-tonumber(lastTs))*tonumber(rate)/1000) -- 剩余的令牌数 leftTokenNum = math.min(capacity,createTokenNum+leftTokenNum) lastTs = nowTs -- 判断是否还有令牌 if leftTokenNum>=need then -- 减去需要的令牌 leftTokenNum = leftTokenNum - need -- 更新 capacity = tonumber(ARGV[1]) rate = tonumber(ARGV[2]) redis.call('hmset',KEYS[1],'capacity',capacity,'rate',rate,'leftTokenNum',leftTokenNum,'lastTs',lastTs) redis.call('expire',KEYS[1],60*60*24) return 1 end return 0 end
标签:capacity,lastTs,redis,ARGV,限流,tonumber,local From: https://www.cnblogs.com/tangs1/p/18231145