redis + lua 脚本实现分布式限流
redis环境搭建,请自行百度。
windows搭建lua环境,参考链接:https://blog.youkuaiyun.com/weixin_41725792/article/details/113827606
redis内置了lua解释器,我们在redis中可以使用redis 关键字 eval 运行Lua代码,如下:
# eval 关键字
# 脚本" return { KEYS[1],ARGV[1]} "
# 2 参数个数
# 参数 K1 K2 ,值 V1 V2
eval " return { KEYS[1],ARGV[1]} " 2 K1 K2 V1 V2
redis预加载:
script load "return 'aaa'"
evalsha "e20bf1be2a7b6dc909965de4a871a2b34a6d900d" 0
带参数:
# lua 连接符是 ..
script load "return 'hello '..KEYS[1]"
evalsha "c42984269dae236a5a42bea45409b728a873605e" 1 jiabengshi
# 查看脚本是否存在 存在返回1 不存在返回0
script exists "c42984269dae236a5a42bea45409b728a873605e"
# 清空脚本
script flush
接下来进入正题:使用java操作redis,实现分布式限流。
1. 编写lua限流脚本
-- 声明变量
local methodKey = KEYS[1]
-- 打印在控制台
print("key is "..methodKey)
-- redis控制台打印日志 注意配置文件配置等级 可去配置文件中logfile="" 路劲下查看
redis.log(redis.LOG_DEBUG, "key is ", methodKey)
-- 传入的限流值
print("value is "..ARGV[1])
local limit = tonumber(ARGV[1])
print("convert is "..limit)
-- 获取当前限流个数 可能为nil(key不存在)
local count = tonumber(redis.call("get", methodKey) or "0")
print("count is "..count)
if count + 1 > limit then
-- 超出限流数 拒绝
redis.log(redis.LOG_INFO, "limit result is ", false)
return false
end
-- 自增1
redis.call('INCRBY',methodKey,1)
-- 设置过期时间 一秒
redis.call('EXPIRE',methodKey,1