Redisson 限流器源码分析
Redisson 限流器源码分析
对上篇文章网友评论给出问题进行解答:redis 的key 是否会过期
可以先阅读上篇文章:
redis + AOP + 自定义注解实现接口限流 - 古渡蓝按 - 博客园 (cnblogs.com)
注解AOP 代码部分提取

// 调用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);
源码分析
源码截图:

1.
分析: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]) 等命令,尝试对 Redis 的 Hash 数据结构进行设置操作。
首先尝试设置 '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;
}
}
如果代码写的有问题,欢迎大家评论交流,进行指点!!!
也希望大家点个关注哦~~~~~~~~
Redisson 限流器源码分析的更多相关文章
- 时间轮机制在Redisson分布式锁中的实际应用以及时间轮源码分析
本篇文章主要基于Redisson中实现的分布式锁机制继续进行展开,分析Redisson中的时间轮机制. 在前面分析的Redisson的分布式锁实现中,有一个Watch Dog机制来对锁键进行续约,代码 ...
- Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析
原文:Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析 一.RedissonLock#lock 源码分析 1.根据锁key计算出 slot,一个slot对 ...
- Springboot基于Redisson实现Redis分布式可重入锁【案例到源码分析】
一.前言 我们在实现使用Redis实现分布式锁,最开始一般使用SET resource-name anystring NX EX max-lock-time进行加锁,使用Lua脚本保证原子性进行实现释 ...
- RedissonLock分布式锁源码分析
最近碰到的一个问题,Java代码中写了一个定时器,分布式部署的时候,多台同时执行的话就会出现重复的数据,为了避免这种情况,之前是通过在配置文件里写上可以执行这段代码的IP,代码中判断如果跟这个IP相等 ...
- 【JDK】JDK源码分析-Semaphore
概述 Semaphore 是并发包中的一个工具类,可理解为信号量.通常可以作为限流器使用,即限制访问某个资源的线程个数,比如用于限制连接池的连接数. 打个通俗的比方,可以把 Semaphore 理解为 ...
- [源码分析] OpenTracing之跟踪Redis
[源码分析] OpenTracing之跟踪Redis 目录 [源码分析] OpenTracing之跟踪Redis 0x00 摘要 0x01 总体逻辑 1.1 相关概念 1.2 埋点插件 1.3 总体逻 ...
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
- zookeeper源码分析之五服务端(集群leader)处理请求流程
leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...
随机推荐
- 代码写错分支,如何提交到另一个分支上【Git把当前分支上的修改转移到另一个分支上】
Git把当前分支上的修改转移到另一个分支上: 1.先在当前分支commit 2.获取本次commit的ID(会获取到一个长id如:ae71cfaf9e865682e2c008aa867e8fbef7a ...
- Signalr断线重连机制
前言 Signalr 即时消息发布到服务器后发现链接老是自动断开,导致无法发送广播后面百度搜了一下,signalr有个超时的机制 解决办法(js) //链接到自己的hub var connection ...
- js扩展方法(自用)
//字符串转Date 字符串格式 yyyy-MM-dd HH:mm:ssString.prototype.toDate = function() { var date = eval('new Date ...
- Greenplum Jdbc 调用 SETOF refcursor
最近公司需要用Greenplum,在调用 jdbc的时候遇到了一些问题.由于我们前提的业务都是使用 sqlserver,sqlserver的 procedure 在前端展示做数据源的时候才用的非常多, ...
- 如何在ubuntu上安装QQ音乐
最简单易懂的安装QQ音乐教程,亲测可用!教程如下: 点击下方网址,进入QQ音乐下载页网址: https://y.qq.com/download/download.html 页面 点击Linux下方的下 ...
- 力扣92(java&python)-反转链表Ⅱ(中等)
题目: 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right .请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 . ...
- OpenKruise v1.1:功能增强与上游对齐,大规模场景性能优化
简介:在 v1.1 版本中,OpenKruise 对不少已有功能做了扩展与增强,并且优化了在大规模集群中的运行性能.以下对 v1.1 的部分功能做简要介绍. 作者:酒祝(王思宇) 云原生应用自动化管理 ...
- 开源 1 年半 star 破 1.2 万的 Dapr 是如何在阿里落地的?
简介: Dapr 是 2019 年 10 月微软开源的可移植.事件驱动分布式运行时,它使开发人员能够轻松地构建运行在云平台和边缘的弹性而微服务化的无状态和有状态的应用程序,从而降低基于微服务架构构建现 ...
- [GPT] 有哪些人工智能辅助工具?
开发人工智能辅助工具可以帮助人们更高效地完成各种任务,并提高生产力和创造力.这些工具可以基于机器学习.深度学习等技术,通过对大量数据进行分析和学习,提供自动化的解决方案. 例如,一个文本翻译工具可 ...
- [PHP] Laravel 依赖注入使用不当引起的内存溢出
业务逻辑: 正常在 controller 方法的参数中注入某个类,方法中使用这个类时发生内存超出提示. 分析: 过往显示,正常使用依赖注入是不存在问题的,那么很有可能是哪里发生了循环引用,导致一直请求 ...