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…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
