redis实现限流
令牌桶逻辑

计算逻辑:

代码:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;/*** @ClassName RedisRateLimiterTokenBucket* @Description TODO* @Author zhang zhengdong* @DATE 2025/1/17 20:22* @Version 1.0*/
public class RedisRateLimiterTokenBucket {private JedisPool jedisPool;private String rateLimitKey;private int timeWindow; // 限制的时间窗口,单位为秒private int maxTokens; // 每个时间窗口的最大令牌数private int refillRate; // 每秒钟生成的令牌数public RedisRateLimiterTokenBucket(JedisPool jedisPool, String rateLimitKey, int timeWindow, int maxTokens, int refillRate) {this.jedisPool = jedisPool;this.rateLimitKey = rateLimitKey;this.timeWindow = timeWindow;this.maxTokens = maxTokens;this.refillRate = refillRate;}/*** 尝试获取令牌*/public boolean acquire() {try (Jedis jedis = jedisPool.getResource()) {long currentTime = System.currentTimeMillis() / 1000;String key = rateLimitKey + ":tokens";String lastRefillKey = rateLimitKey + ":lastRefillTime";// 获取最后一次令牌补充的时间String lastRefillTime = jedis.get(lastRefillKey);if (lastRefillTime == null) {jedis.set(lastRefillKey, String.valueOf(currentTime));jedis.set(key, String.valueOf(maxTokens));lastRefillTime = String.valueOf(currentTime);}// 计算补充令牌的数量long elapsed = currentTime - Long.parseLong(lastRefillTime);int tokensToAdd = (int) (elapsed * refillRate);// 计算当前令牌数int tokens = Integer.parseInt(jedis.get(key));tokens = Math.min(tokens + tokensToAdd, maxTokens);// 如果令牌数大于 0,则消费一个令牌if (tokens > 0) {jedis.set(key, String.valueOf(tokens - 1));jedis.set(lastRefillKey, String.valueOf(currentTime));return true;}return false; // 没有令牌,拒绝请求}}
}
验证代码
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;/*** @ClassName RedisRateLimiterTokenBucketTest* @Description TODO* @Author zhang zhengdong* @DATE 2025/1/17 20:25* @Version 1.0*/
public class RedisRateLimiterTokenBucketTest {public static void main(String[] args) {// 初始化 Jedis 连接池JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(10);JedisPool jedisPool = new JedisPool(poolConfig, "localhost", 6379);// 限流设置:10 秒内最多 20 次请求int timeWindow = 10;int maxRequestsPerWindow = 10;// 使用 令牌桶 算法实现限流RedisRateLimiterTokenBucket rateLimiterTokenBucket = new RedisRateLimiterTokenBucket(jedisPool,"rate_limit_token_bucket", timeWindow, maxRequestsPerWindow, 1);for (int i = 0; i < 25; i++) {boolean allowed = rateLimiterTokenBucket.acquire();if (allowed) {System.out.println("请求 " + (i + 1) + " 被允许");} else {System.out.println("请求 " + (i + 1) + " 被拒绝");}// try {
// Thread.sleep(400); // 模拟请求间隔
// } catch (InterruptedException e) {
// e.printStackTrace();
// }}}
}
zset实现限流逻辑

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;import java.util.UUID;/*** @ClassName RedisRateLimiterZSet* @Description TODO* @Author zhang zhengdong* @DATE 2025/1/17 19:50* @Version 1.0*/
public class RedisRateLimiterZSet {private JedisPool jedisPool;private String rateLimitKey;private int timeWindow; // 限制的时间窗口,单位为秒private int maxRequestsPerWindow; // 每个窗口允许的最大请求次数public RedisRateLimiterZSet(JedisPool jedisPool, String rateLimitKey, int timeWindow, int maxRequestsPerWindow) {this.jedisPool = jedisPool;this.rateLimitKey = rateLimitKey;this.timeWindow = timeWindow;this.maxRequestsPerWindow = maxRequestsPerWindow;}public boolean acquire() {try (Jedis jedis = jedisPool.getResource()) {Long currentTime = System.currentTimeMillis();System.out.println(currentTime);if (jedis.zcard(rateLimitKey) > 0) {Integer count = jedis.zrangeByScore(rateLimitKey, currentTime - 10 * 1000, currentTime).size(); // 注意这里使用zrangeByScore,以时间作为score。zrange key start stop 命令的start和stop是序号。System.out.println(count);if (count != null && count > maxRequestsPerWindow) {return false;}}jedis.zadd(rateLimitKey, Double.valueOf(currentTime), UUID.randomUUID().toString());return true;}}}
测试
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;/*** @ClassName RateLimiterZSetTest* @Description TODO* @Author zhang zhengdong* @DATE 2025/1/17 20:00* @Version 1.0*/
public class RedisRateLimiterZSetTest {public static void main(String[] args) {JedisPoolConfig jedisConfig = new JedisPoolConfig();jedisConfig.setMaxTotal(10);JedisPool jedisPool = new JedisPool(jedisConfig, "localhost", 6379);// 限流设置:10 秒内最多 20 次请求RedisRateLimiterZSet rateLimiter = new RedisRateLimiterZSet(jedisPool, "rate_limit_zset", 10, 20);// 测试:连续请求for (int i = 0; i < 25; i++) {boolean allowed = rateLimiter.acquire();if (allowed) {System.out.println("请求 " + (i + 1) + " 被允许");} else {System.out.println("请求 " + (i + 1) + " 被拒绝");}// 延迟 400ms 后再次尝试
// try {
// Thread.sleep(400); // 模拟请求间隔
// } catch (InterruptedException e) {
// e.printStackTrace();
// }}}
相关文章:
redis实现限流
令牌桶逻辑 计算逻辑: 代码: import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;/*** ClassName RedisRateLimiterTokenBucket* Description TODO* Author zhang zhengdong* DATE 2025/1/17 20:22* Version 1.0*/ public class…...
基于SpringBoot和PostGIS的各国及所属机场信息检索及可视化实现
目录 前言 一、空间数据简介 1、全球国家信息表 2、机场信息表 3、国家机场检索实现 二、SpringBoot后台实现 1、模型层实现 2、控制层实现 三、WebGIS可视化实现 1、Leaflet界面实现 2、国家及其机场可视化成果 3、全球机场数量排行榜 四、总结 前言 新春佳节即将…...
python http server运行Angular 单页面路由时重定向,解决404问题
问题 当Angular在本地ng server运行时候,可以顺利访问各级路由。 但是运行ng build后,在dist 路径下的打包好的额index.html 必须要在服务器下运行才能加载。 在服务器下我们第一次访问路由页面时是没有问题的,但是尝试刷新页面或手动输入路…...
GPT-4o背后的语音技术
GPT-4o背后的语音技术 GPT-4o是一个any2any的多模态模型,能够接受文本、音频、图像、视频等多模态输入,也能够生成包含文本、语音、图像和视频等混合内容的多模态输出。本文主要谈语音多模态的实现,并分享一些对于语音研究未来发展的看法。 GPT-4o (“o” 代表 “omni”) …...
微透镜阵列精准全检,白光干涉3D自动量测方案提效70%
广泛应用的微透镜阵列 微透镜是一种常见的微光学元件,通过设计微透镜,可对入射光进行扩散、光束整形、光线均分、光学聚焦、集成成像等调制,进而实现许多传统光学元器件难以实现的特殊功能。 微透镜阵列(Microlens Array&#x…...
Spring boot框架下的RocketMQ消息中间件
1. RocketMQ 基础概念 1.1 核心概念 以下是 RocketMQ 核心概念在 Spring Boot 的 Java 后端代码中的实际使用方式: Producer(生产者) 定义:Producer 是负责发送消息到 RocketMQ 的组件。它可以将消息发送到指定的 Topic。 实…...
记录一次 centos 启动失败
文章目录 现场1分析1现场2分析2搜索实际解决过程 现场1 一次断电,导致 之前能正常启动的centos 7.7 起不来了有部分log , 关键信息如下 [1.332724] XFS(sda3): Internal error xfs ... at line xxx of fs/xfs/xfs_trans.c [1.332724] XFS(sda3): Corruption of in-memory data…...
C++学习第五天
创作过程中难免有不足,若您发现本文内容有误,恳请不吝赐教。 提示:以下是本篇文章正文内容,下面案例可供参考 一、构造函数 问题1 关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下…...
openharmony标准系统方案之瑞芯微RK3568移植案例
标准系统方案之瑞芯微RK3568移植案例 本文章是基于瑞芯微RK3568芯片的DAYU200开发板,进行标准系统相关功能的移植,主要包括产品配置添加,内核启动、升级,音频ADM化,Camera,TP,LCD,…...
深入理解 SSH 端口转发:本地 vs 远程 vs 动态转发
🌟 简介 SSH 端口转发(SSH Port Forwarding)作为一种强大而灵活的技术,不仅可以帮助我们安全地访问远程服务,还能轻松突破网络限制。本文将带你深入了解 SSH 端口转发的原理、类型和实战应用。 🌈 目录 &a…...
postman请求参数化
postman界面介绍 一、使用环境变量(Environment Variables)进行参数化 1、在请求中使用环境变量 在请求的url、请求头(Headers)、请求体(Body)等部分都可以使用环境变量。 URL 部分示例 点击 Postman 界面右上角的 “眼睛” 图标(Environment Quick Look)打开环境管理…...
基于 WEB 开发的汽车养护系统设计与实现
标题:基于 WEB 开发的汽车养护系统设计与实现 内容:1.摘要 本文介绍了基于 WEB 开发的汽车养护系统的设计与实现。文章首先阐述了系统的背景和目的,即随着汽车保有量的增加,汽车养护需求日益增长,传统的汽车养护方式已经无法满足人们的需求&…...
Nginx正向代理配置
Nginx 正向代理默认只支持 http 协议,不支持 https 协议,需借助 "ngx_http_proxy_connect_module" 模块实现 https 正向代理,详情请参考: https://github.com/chobits/ngx_http_proxy_connect_module 安装Nginx某些模块…...
本地仓库管理之当前分支内的操作
以刚搭建好的git仓库为例,刚搭建完的仓库只有master分支,使用git branch查看当前的分支情况。 elfubuntu:~/work/example/hello$ git branch *所在分支为当前分支,即master分支 当前分支进行源码修改时简单流程图如下: 在当前分…...
《内网穿透:网络拓展与安全防护的平衡艺术》
一、引言:开启内网穿透的大门 在当今数字化浪潮席卷全球的时代,网络已成为人们生活和工作中不可或缺的一部分。我们日常使用的网络,如同一个庞大而复杂的生态系统,其中内网和外网犹如两个相互关联却又有所区别的世界。 想象一下…...
【python写个可以运行的2048小游戏】
写一个完整的2048小游戏在Python中是一个相对复杂的任务,因为它涉及到用户界面、事件处理、游戏逻辑等多个方面。为了简化这个过程,我们可以使用Python的图形库,比如pygame。下面是一个简单的2048游戏的实现。 首先,确保你已经安…...
【Flink系列】9. Flink容错机制
9. 容错机制 在Flink中,有一套完整的容错机制来保证故障后的恢复,其中最重要的就是检查点。 9.1 检查点(Checkpoint) 9.1.1 检查点的保存 1)周期性的触发保存 “随时存档”确实恢复起来方便,可是需要我…...
DETR论文阅读
1. 动机 传统的目标检测任务需要大量的人工先验知识,例如预定义的先验anchor,NMS后处理策略等。这些人工先验知识引入了很多人为因素,且较难处理。如果能够端到端到直接生成目标检测结果,将会使问题变得很优雅。 2. 主要贡献 提…...
关于vite+vue3+ts项目中env.d.ts 文件详解
env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示,特别是在使用一些特定于 Vite 的功能时(如 import.meta.env)。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…...
如何优化Elasticsearch大文档查询?
记录一次业务复杂场景下DSL优化的过程 背景 B端商城业务有一个场景就是客户可见的产品列表是需要N多闸口及各种其它逻辑组合过滤的,各种闸口数据及产品数据都是存储在ES的(有的是独立索引,有的是作为产品属性存储在产品文档上)。 在实际使用的过程中&a…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
