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<String> keys = new ArrayList<>();
  keys.add("判断用户的key");
  List<String> args = new ArrayList<>();
  args.add("60");//key的存活时间, 60秒
  jedis.evalsha(scriptSha, keys, args);     
} catch (Exception e) {
  System.out.println("请求过于频繁");
  ......
} finally {
  jedis.close();
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Lua脚本 Redis的单一指令都是原子的,可以有效保证执行结果要么成功要么失败;当用户要执行多条数据时,一方面每...
    李小磊_0867阅读 3,575评论 3 5
  • Zookeeper用于集群主备切换。 YARN让集群具备更好的扩展性。 Spark没有存储能力。 Spark的Ma...
    Yobhel阅读 7,385评论 0 34
  • 教你看懂redis配置 – 安全 我们可以要求redis客户端在向redis-server发送请求之前,先进行密码...
    烨枫_邱阅读 319评论 0 1
  • Redis Lua 这个技术,我之前就在关注,今天有空,我把项目中基于Redis实现的ID生成器改成用lua脚本实...
    土豆肉丝盖浇饭阅读 42,686评论 5 20
  • 每个人都有不得不努力的理由,谁都不比谁容易,都宽容一下自己和别人,不让别人和自己太过艰难。
    山河永寂的长情阅读 316评论 0 2