> 技术文档 > 【Redis】解析Redisson 限流器源码_redisson trysetrate

【Redis】解析Redisson 限流器源码_redisson trysetrate


Redisson

    • 一、注解AOP 代码部分提取
    • 二、设置限流器的失效时间

在这里插入图片描述
在这里插入图片描述

一、注解AOP 代码部分提取

【Redis】解析Redisson 限流器源码_redisson trysetrate

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

redis 工具类

public class RedisUtils { private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class); /** * 限流 * * @param key 限流key * @param rateType 限流类型 * @param rate 速率 * @param rateInterval 速率间隔 * @return -1 表示失败 */ public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) { // 获取一个限流器 RRateLimiter rateLimiter = CLIENT.getRateLimiter(key); // 将限流的配置信息保存在Redis中 rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS); // tryAcquire 用于获取当前可用的许可数 if (rateLimiter.tryAcquire()) { return rateLimiter.availablePermits(); } else { return -1L; } }} 

解析

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

源码分析
源码截图:

【Redis】解析Redisson 限流器源码_redisson trysetrate

分析:trySetRate 调用 trySetRateAsync 方法

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

逐步分析代码:

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

源码lua 脚本解释

– 源码lua 脚本

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

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

二、设置限流器的失效时间

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

修改后代码:

/** * 限流 * * @param key 限流key * @param rateType 限流类型 * @param rate 速率 * @param rateInterval 速率间隔 * @param expirationTimeInSeconds 过期时间(秒) * @param isExpire 是否设置限流器过期 * @return -1 表示失败 */public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval, long expirationTimeInSeconds,boolean isExpire) { RRateLimiter rateLimiter = CLIENT.getRateLimiter(key); rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS); if(isExpire){ // 是否设置过期时间 rateLimiter.expire(expirationTimeInSeconds, TimeUnit.SECONDS); } if (rateLimiter.tryAcquire()) { return rateLimiter.availablePermits(); } else { return -1L; }}

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