经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Redis » 查看文章
Redisson 限流器源码分析
来源:cnblogs  作者:古渡蓝按  时间:2024/6/5 9:23:54  对本文有异议

Redisson 限流器源码分析

对上篇文章网友评论给出问题进行解答:redis 的key 是否会过期

可以先阅读上篇文章:

redis + AOP + 自定义注解实现接口限流 - 古渡蓝按 - 博客园 (cnblogs.com)

注解AOP 代码部分提取

  1. // 调用Reids工具类的rateLimiter 方法
  2. long number = RedisUtils.rateLimiter(combineKey, rateType, count, time);

redis 工具类

  1. public class RedisUtils {
  2. private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
  3. /**
  4. * 限流
  5. *
  6. * @param key 限流key
  7. * @param rateType 限流类型
  8. * @param rate 速率
  9. * @param rateInterval 速率间隔
  10. * @return -1 表示失败
  11. */
  12. public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) {
  13. // 获取一个限流器
  14. RRateLimiter rateLimiter = CLIENT.getRateLimiter(key);
  15. // 将限流的配置信息保存在Redis中
  16. rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
  17. // tryAcquire 用于获取当前可用的许可数
  18. if (rateLimiter.tryAcquire()) {
  19. return rateLimiter.availablePermits();
  20. } else {
  21. return -1L;
  22. }
  23. }
  24. }

解析

rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);

源码分析

源码截图:


1.
分析:trySetRate 调用 trySetRateAsync 方法

  1. @Override
  2. public boolean trySetRate(RateType type, long rate, long rateInterval, RateIntervalUnit unit) {
  3. return get(trySetRateAsync(type, rate, rateInterval, unit));
  4. }
  5. @Override
  6. public RFuture<Boolean> trySetRateAsync(RateType type, long rate, long rateInterval, RateIntervalUnit unit) {
  7. return commandExecutor.evalWriteNoRetryAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
  8. "redis.call('hsetnx', KEYS[1], 'rate', ARGV[1]);"
  9. + "redis.call('hsetnx', KEYS[1], 'interval', ARGV[2]);"
  10. + "return redis.call('hsetnx', KEYS[1], 'type', ARGV[3]);",
  11. Collections.singletonList(getRawName()), rate, unit.toMillis(rateInterval), type.ordinal());
  12. }

逐步分析代码:

  • commandExecutor.evalWriteNoRetryAsync():这里使用了 Redis 的 EVAL 命令,这个命令允许执行 Lua 脚本,而不会受到 Redis 的同步阻塞操作。
  • getRawName():这是获取限流器的名称或标识。
  • RedisCommands.EVAL_BOOLEAN:表示执行 Lua 脚本后期望的返回值类型为 Boolean。

源码lua 脚本解释

  1. -- 源码lua 脚本
  2. "redis.call('hsetnx', KEYS[1], 'rate', ARGV[1]);"
  3. + "redis.call('hsetnx', KEYS[1], 'interval', ARGV[2]);"
  4. + "return redis.call('hsetnx', KEYS[1], 'type', ARGV[3]);"
  5. --- 解释
  6. 这段 Lua 脚本中,通过 redis.call('hsetnx', KEYS[1], 'rate', ARGV[1]) 等命令,尝试对 Redis Hash 数据结构进行设置操作。
  7. 首先尝试设置 'rate' 字段为传入的速率值;
  8. 然后尝试设置 'interval' 字段为传入的时间间隔值;
  9. 最后尝试设置 'type' 字段为传入的类型值。这里使用了 hsetnx 命令来进行设置操作,如果字段已存在,则不会进行设置操作。
  • Collections.singletonList(getRawName()):将限流器的名称作为参数传递给 Lua 脚本。
  • rate, unit.toMillis(rateInterval), type.ordinal():这三个参数分别是速率、时间间隔以毫秒为单位、以及限流类型

总结:这段代码本身并没有提供设置限流器自动过期的功能。在 Redisson 中,限流器自动过期的功能通常不是默认包含在限流器的设置中。

设置限流器的失效时间

限流器自动过期(是指的是限流这个功能),可以使用expire进行失效时间设置

修改后代码:

  1. /**
  2. * 限流
  3. *
  4. * @param key 限流key
  5. * @param rateType 限流类型
  6. * @param rate 速率
  7. * @param rateInterval 速率间隔
  8. * @param expirationTimeInSeconds 过期时间(秒)
  9. * @param isExpire 是否设置限流器过期
  10. * @return -1 表示失败
  11. */
  12. public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval, long expirationTimeInSeconds,boolean isExpire) {
  13. RRateLimiter rateLimiter = CLIENT.getRateLimiter(key);
  14. rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
  15. if(isExpire){
  16. // 是否设置过期时间
  17. rateLimiter.expire(expirationTimeInSeconds, TimeUnit.SECONDS);
  18. }
  19. if (rateLimiter.tryAcquire()) {
  20. return rateLimiter.availablePermits();
  21. } else {
  22. return -1L;
  23. }
  24. }

如果代码写的有问题,欢迎大家评论交流,进行指点!!!

也希望大家点个关注哦~~~~~~~~

原文链接:https://www.cnblogs.com/blbl-blog/p/18231765

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号