Redis实现限制请求频率

本文的初衷仅供自己做备忘笔记, 内容大多从网上搜集和整理, 并非都是自己原创.
参考的来源我会在后面注明, 对于可能遗漏的来源, 还请相关原创作者提醒, 非常感谢.

参考来源:
https://www.cnblogs.com/niuben/p/10812369.html

在网上搜了不少方案, 最终选择了参照参考来源1的文章中的方案3, 进行适当修改以适应当前项目.
最终以用户为单位, 对其请求接口频率进行控制.

逻辑

把限制逻辑封装到一个Lua脚本中,调用时只需传入:key、限制数量、过期时间,调用结果就会指明是否运行访问


02266ba7.png

lua脚本(这里java字符串对双引号进行了处理)

local notexists = redis.call(\"set\", KEYS[1], 1, \"NX\", \"EX\", tonumber(ARGV[2]))
if (notexists) then
  return 1
end
local current = tonumber(redis.call(\"get\", KEYS[1]))
if (current == nil) then
  local result = redis.call(\"incr\", KEYS[1])
  redis.call(\"expire\", KEYS[1], tonumber(ARGV[2]))
  return result
end
if (current >= tonumber(ARGV[1])) then
  error(\"too many requests\")
end
local result = redis.call(\"incr\", KEYS[1])
return result

使用 eval 调用脚本

eval 脚本 1 key 参数(允许的最大次数) 参数(过期时间)

正常执行时, redis会返回key对应的数字, 而超过限制后, redis会返回error异常
java代码(部分)

String script = "lua脚本";
String scriptSha = "事先存好的脚本sha"
......
Jedis jedis = JedisPool.getJedisInstance();
if(!jedis.scriptExists(getRedisScriptHash())) {//判断脚本是否存在
 scriptSha = jedis.scriptLoad(lua脚本);//写入脚本
}
try {
  List keys = new ArrayList<>();
  keys.add("判断用户的key");
  List args = new ArrayList<>();
  args.add("60");//key的存活时间, 60秒
  jedis.evalsha(scriptSha, keys, args);     
} catch (Exception e) {
  System.out.println("请求过于频繁");
  ......
} finally {
  jedis.close();
}

你可能感兴趣的:(Redis实现限制请求频率)