Redisson 限流器源码分析

打印 上一主题 下一主题

主题 906|帖子 906|积分 2718

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.         // 获取一个限流器
  15.         RRateLimiter rateLimiter = CLIENT.getRateLimiter(key);
  16.         // 将限流的配置信息保存在Redis中
  17.         rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
  18.         // tryAcquire 用于获取当前可用的许可数
  19.         if (rateLimiter.tryAcquire()) {
  20.             return rateLimiter.availablePermits();
  21.         } else {
  22.             return -1L;
  23.         }
  24.     }
  25. }   
复制代码
解析
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.    
  14.     RRateLimiter rateLimiter = CLIENT.getRateLimiter(key);
  15.    
  16.     rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
  17.    
  18.     if(isExpire){
  19.         // 是否设置过期时间
  20.        rateLimiter.expire(expirationTimeInSeconds, TimeUnit.SECONDS);
  21.     }
  22.     if (rateLimiter.tryAcquire()) {
  23.         return rateLimiter.availablePermits();
  24.     } else {
  25.         return -1L;
  26.     }
  27. }
复制代码
如果代码写的有问题,欢迎大家评论交流,进行辅导!!!
也希望大家点个关注哦~~~~~~~~

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

科技颠覆者

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表