Redis实现滑动窗口限流
import redis
import time
# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)
# 滑动窗口限流实现
def is_rate_limited(key, max_requests, window_size):
# 计算窗口结束时间
window_end = time.time() + window_size
# 计算当前窗口的开始时间
window_start = window_end - window_size
# 使用Lua脚本原子操作来记录请求和检查是否超出限制
lua_script = """
local requests = redis.call('incr', KEYS[1])
if requests == 1 then
redis.call('expire', KEYS[1], KEYS[2])
end
if requests > tonumber(ARGV[1]) then
return 1 -- 超出限制
else
return 0 -- 未超出限制
end
"""
# 调用Lua脚本
result = r.eval(lua_script, 2, key, str(window_size), str(max_requests))
# 如果已超出限制,设置延时直到下一个窗口
if result == 1:
time.sleep(window_end - time.time())
return True
else:
return False
# 使用示例
key = 'user_123'
max_requests = 10
window_size = 60 # 窗口大小为60秒
# 每次请求前调用此函数来检查是否超出限制
if is_rate_limited(key, max_requests, window_size):
print("请求超出限制")
else:
print("请求未超出限制")
这段代码使用了Redis的incr
命令来原子地增加计数,并通过Lua脚本与Redis的事务特性来确保整个操作的原子性。如果请求超出了限制,它会计算当前时间与窗口结束时间的差值,并延迟当前线程直到下一个窗口开始。这样可以确保在限制时间窗内的请求数量不会超过预设的最大请求数。
评论已关闭