首页 > 数据库 >Redisson 限流器源码分析

Redisson 限流器源码分析

时间:2024-06-04 21:22:34浏览次数:37  
标签:Redisson return rateLimiter param rateInterval rate 限流 源码

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,return,rateLimiter,param,rateInterval,rate,限流,源码
From: https://www.cnblogs.com/blbl-blog/p/18231765

相关文章

  • 新版校园跑腿外卖独立版+APP+小程序前端外卖配送平台源码
    源码介绍:同城校园跑腿外卖配送平台源码,支持自定义diy你可以设计你的页面,设计你自己的风格,支持多校园,独立版本,多商户,有用户端,骑手端,商家端,强大的功演示截图:安装说明:服务器2h4G5M即可,服务器系统:centos8,服务器上安装宝塔面板,不懂怎么安装宝塔的可以百度,所需环境:php7.3......
  • containerd 源码分析:创建 container(三)
    文接containerd源码分析:创建container(二)1.2.2.2启动task上节介绍了创建task,task创建之后将返回response给ctr。接着,ctr调用task.Start启动容器。//containerd/client/task.gofunc(t*task)Start(ctxcontext.Context)error{ r,err:=t.client.TaskServi......
  • springboot智慧校园管理系统的设计与实现(文档+源码)
    大家好,我是永钊,一个混迹在java圈的码农,今天要和大家聊的是一款基于springboot的智慧校园管理系统,项目源码请联系永钊,目前有各类成品毕设javawebsshssmspringboot等等项目框架,源码丰富,欢迎咨询。 本网站系统采用了Mysql数据库,Java语言,SpringBoot框架等技术进行编程实......
  • springboot的设计与实现(文档+源码)足球青训俱乐部管理后台系统
    大家好,我是永钊,一个混迹在java圈的码农,今天要和大家聊的是一款基于springboot的足球青训俱乐部管理后台系统,项目源码请联系永钊,目前有各类成品毕设javawebsshssmspringboot等等项目框架,源码丰富,欢迎咨询。 本网站系统重点阐述了足球青训俱乐部管理后台系统的开发过程,......
  • 网关限流功能性能优化
    本文主要从设计与原理方面分享优化过程中的思考,不涉及具体的代码实现。在分析过程中我会写一些当时思考的问题,在看后续答案时可以自己也先思考一下老的限流方案首先讲解一下原本网关限流功能的实现方案,省略其中的白名单,黑名单,令牌桶算法实现等一些细节限流策略中包含多种策略,......
  • 在线考试|基于Springboot的在线考试管理系统设计与实现(源码+数据库+文档)
    在线考试管理系统目录目录基于Springboot的在线考试管理系统设计与实现一、前言二、系统设计三、系统功能设计 1、前台:2、后台管理员功能四、数据库设计 五、核心代码 六、论文参考七、最新计算机毕设选题推荐八、源码获取:博主介绍:✌️大厂码农|毕设布道师,......
  • 健身管理小程序|基于微信开发健身管理小程序的系统设计与实现(源码+数据库+文档)
    健身管理小程序目录基于微信开发健身管理小程序设计与实现一、前言二、系统设计三、系统功能设计 小程序端:后台四、数据库设计 五、核心代码 六、论文参考七、最新计算机毕设选题推荐八、源码获取:博主介绍:✌️大厂码农|毕设布道师,阿里云开发社区乘风者计划专......
  • 电影交流|基于SprinBoot+vue的电影交流平台小程序系统(源码+数据库+文档)
     电影交流平台目录目录基于SprinBoot+vue的电影交流平台小程序系统 一、前言 二、系统设计三、系统功能设计 1用户信息管理2电影信息管理3公告信息管理4论坛信息管理四、数据库设计 五、核心代码 六、论文参考七、最新计算机毕设选题推荐八、源码获取:......
  • redis限流
    前提redis+lua 滑动窗口--滑动窗口localkey=KEYS[1]localmaxSize=ARGV[1]localcurrentTime=ARGV[2]localstartTime=ARGV[3]localuuid=ARGV[4]localcurrentCount=redis.call('zcount',key,startTime,currentTime)if(currentCountandtonumber......
  • 分享一个Python爬虫入门实例带数据分析(有源码,学习使用)
    Python爬虫是一种使用Python编程语言实现的自动化获取网页数据的技术。它广泛应用于数据采集、数据分析、网络监测等领域。以下是对Python爬虫的详细介绍:架构和组成:下载器:负责根据指定的URL下载网页内容,常用的库有Requests和urllib。解析器:用于解析下载的网页内容,提取所......