当前位置: 首页 > news >正文

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实现限流

令牌桶逻辑 计算逻辑&#xff1a; 代码&#xff1a; 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运行时候&#xff0c;可以顺利访问各级路由。 但是运行ng build后&#xff0c;在dist 路径下的打包好的额index.html 必须要在服务器下运行才能加载。 在服务器下我们第一次访问路由页面时是没有问题的&#xff0c;但是尝试刷新页面或手动输入路…...

GPT-4o背后的语音技术

GPT-4o背后的语音技术 GPT-4o是一个any2any的多模态模型,能够接受文本、音频、图像、视频等多模态输入,也能够生成包含文本、语音、图像和视频等混合内容的多模态输出。本文主要谈语音多模态的实现,并分享一些对于语音研究未来发展的看法。 GPT-4o (“o” 代表 “omni”) …...

微透镜阵列精准全检,白光干涉3D自动量测方案提效70%

广泛应用的微透镜阵列 微透镜是一种常见的微光学元件&#xff0c;通过设计微透镜&#xff0c;可对入射光进行扩散、光束整形、光线均分、光学聚焦、集成成像等调制&#xff0c;进而实现许多传统光学元器件难以实现的特殊功能。 微透镜阵列&#xff08;Microlens Array&#x…...

Spring boot框架下的RocketMQ消息中间件

1. RocketMQ 基础概念 1.1 核心概念 以下是 RocketMQ 核心概念在 Spring Boot 的 Java 后端代码中的实际使用方式&#xff1a; Producer&#xff08;生产者&#xff09; 定义&#xff1a;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++学习第五天

创作过程中难免有不足&#xff0c;若您发现本文内容有误&#xff0c;恳请不吝赐教。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、构造函数 问题1 关于编译器生成的默认成员函数&#xff0c;很多童鞋会有疑惑&#xff1a;不实现构造函数的情况下…...

openharmony标准系统方案之瑞芯微RK3568移植案例

标准系统方案之瑞芯微RK3568移植案例 ​本文章是基于瑞芯微RK3568芯片的DAYU200开发板&#xff0c;进行标准系统相关功能的移植&#xff0c;主要包括产品配置添加&#xff0c;内核启动、升级&#xff0c;音频ADM化&#xff0c;Camera&#xff0c;TP&#xff0c;LCD&#xff0c…...

深入理解 SSH 端口转发:本地 vs 远程 vs 动态转发

&#x1f31f; 简介 SSH 端口转发&#xff08;SSH Port Forwarding&#xff09;作为一种强大而灵活的技术&#xff0c;不仅可以帮助我们安全地访问远程服务&#xff0c;还能轻松突破网络限制。本文将带你深入了解 SSH 端口转发的原理、类型和实战应用。 &#x1f308; 目录 &a…...

postman请求参数化

postman界面介绍 一、使用环境变量(Environment Variables)进行参数化 1、在请求中使用环境变量 在请求的url、请求头(Headers)、请求体(Body)等部分都可以使用环境变量。 URL 部分示例 点击 Postman 界面右上角的 “眼睛” 图标(Environment Quick Look)打开环境管理…...

基于 WEB 开发的汽车养护系统设计与实现

标题:基于 WEB 开发的汽车养护系统设计与实现 内容:1.摘要 本文介绍了基于 WEB 开发的汽车养护系统的设计与实现。文章首先阐述了系统的背景和目的&#xff0c;即随着汽车保有量的增加&#xff0c;汽车养护需求日益增长&#xff0c;传统的汽车养护方式已经无法满足人们的需求&…...

Nginx正向代理配置

Nginx 正向代理默认只支持 http 协议&#xff0c;不支持 https 协议&#xff0c;需借助 "ngx_http_proxy_connect_module" 模块实现 https 正向代理&#xff0c;详情请参考&#xff1a; https://github.com/chobits/ngx_http_proxy_connect_module 安装Nginx某些模块…...

本地仓库管理之当前分支内的操作

以刚搭建好的git仓库为例&#xff0c;刚搭建完的仓库只有master分支&#xff0c;使用git branch查看当前的分支情况。 elfubuntu:~/work/example/hello$ git branch *所在分支为当前分支&#xff0c;即master分支 当前分支进行源码修改时简单流程图如下&#xff1a; 在当前分…...

《内网穿透:网络拓展与安全防护的平衡艺术》

一、引言&#xff1a;开启内网穿透的大门 在当今数字化浪潮席卷全球的时代&#xff0c;网络已成为人们生活和工作中不可或缺的一部分。我们日常使用的网络&#xff0c;如同一个庞大而复杂的生态系统&#xff0c;其中内网和外网犹如两个相互关联却又有所区别的世界。 想象一下…...

【python写个可以运行的2048小游戏】

写一个完整的2048小游戏在Python中是一个相对复杂的任务&#xff0c;因为它涉及到用户界面、事件处理、游戏逻辑等多个方面。为了简化这个过程&#xff0c;我们可以使用Python的图形库&#xff0c;比如pygame。下面是一个简单的2048游戏的实现。 首先&#xff0c;确保你已经安…...

【Flink系列】9. Flink容错机制

9. 容错机制 在Flink中&#xff0c;有一套完整的容错机制来保证故障后的恢复&#xff0c;其中最重要的就是检查点。 9.1 检查点&#xff08;Checkpoint&#xff09; 9.1.1 检查点的保存 1&#xff09;周期性的触发保存 “随时存档”确实恢复起来方便&#xff0c;可是需要我…...

DETR论文阅读

1. 动机 传统的目标检测任务需要大量的人工先验知识&#xff0c;例如预定义的先验anchor&#xff0c;NMS后处理策略等。这些人工先验知识引入了很多人为因素&#xff0c;且较难处理。如果能够端到端到直接生成目标检测结果&#xff0c;将会使问题变得很优雅。 2. 主要贡献 提…...

关于vite+vue3+ts项目中env.d.ts 文件详解

env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示&#xff0c;特别是在使用一些特定于 Vite 的功能时&#xff08;如 import.meta.env&#xff09;。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…...

如何优化Elasticsearch大文档查询?

记录一次业务复杂场景下DSL优化的过程 背景 B端商城业务有一个场景就是客户可见的产品列表是需要N多闸口及各种其它逻辑组合过滤的&#xff0c;各种闸口数据及产品数据都是存储在ES的(有的是独立索引&#xff0c;有的是作为产品属性存储在产品文档上)。 在实际使用的过程中&a…...

从模板库到函数调用:解锁CODESYS组件依赖与2小时掉线限制的实战指南

1. 为什么你的CODESYS Runtime总在2小时后掉线&#xff1f; 很多开发者在使用CODESYS开发工业控制项目时&#xff0c;都会遇到一个让人头疼的问题——Runtime运行2小时后就会自动断开连接。这个问题其实源于CODESYS的试用保护机制。官方默认配置会对未授权的组件进行时间限制&a…...

【算法日记 11】贪心之美:用“相邻交换法”秒杀乱序求极值问题

&#x1f680;【算法日记 11】贪心之美&#xff1a;用“相邻交换法”秒杀乱序求极值问题 &#x1f4cd; 场景引入&#xff1a;百醇的终极摆放艺术 今天遇到了一道看似毫无头绪的排列极值题&#xff1a;题目大意&#xff1a;有 NNN 根百醇&#xff0c;每根有长度 AiA_iAi​ 和美…...

小程序在企业数字化转型中的作用是什么?

小程序在企业数字化转型中的作用是什么&#xff1f;一、核心结论小程序在企业数字化转型中的核心作用&#xff0c;不是简单的“线上工具”&#xff0c;而是连接用户、业务与数据的轻量化入口。它通过降低使用门槛与缩短业务路径&#xff0c;使企业能够更高效地完成获客、转化与…...

BR实用操作

文章目录B&R 4.3下载安装B&R 4.3下载开始安装安装结束注意点Upgrdate 安装注册授权Could not find Automation Runtime direcotry N3.34 报错B&R 修改模拟ip删除temp文件默认连接虚拟 onine修改ipBR冗余配置BR模拟配置BR模拟BR授权OPC UA开启和端口设置OPC UA上传配…...

别再轮询了!STM32 ADC多通道采集,用DMA+定时器实现后台自动搬运数据(附CubeMX配置)

STM32 ADC多通道采集&#xff1a;DMA定时器实现零CPU占用的数据搬运方案 在工业传感器监测或物联网设备开发中&#xff0c;ADC多通道采集是基础但关键的技术环节。传统轮询方式不仅占用大量CPU资源&#xff0c;还会因处理延迟导致数据丢失。本文将分享一种基于DMA和定时器触发的…...

高光谱成像基础(完)光谱融合(Spectral Fusion)镀

环境安装 pip install keystone-engine capstone unicorn 这3个工具用法极其简单&#xff0c;下面通过示例来演示其用法。 Keystone 示例 from keystone import * CODE b"INC ECX; ADD EDX, ECX" try: ks Ks(KS_ARCH_X86, KS_MODE_64) encoding, count ks.…...

MPL3115A2传感器驱动开发与嵌入式高度气压测量实战

1. MPL3115A2 压力/高度/温度传感器深度技术解析 MPL3115A2 是 NXP&#xff08;现为恩智浦半导体&#xff09;推出的一款高精度、低功耗、IC 接口的绝对压力传感器&#xff0c;集成温度测量与气压高度计算引擎。该器件并非简单的模拟信号采集芯片&#xff0c;而是一个具备完整数…...

如何轻松实现微信聊天永久备份:新手完整指南

如何轻松实现微信聊天永久备份&#xff1a;新手完整指南 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeChatMsg …...

保姆级 uPyPi 教程|从 到 :MicroPython 驱动包一键安装 + 分享全攻略交

这个代码的核心功能是&#xff1a;基于输入词的长度动态选择反义词示例&#xff0c;并调用大模型生成反义词&#xff0c;体现了 “动态少样本提示&#xff08;Dynamic Few-Shot Prompting&#xff09;” 与 “上下文长度感知的示例选择” 的能力。 from langchain.prompts impo…...

终极指南:如何在Chrome浏览器中免费实现KeePass密码自动填充

终极指南&#xff1a;如何在Chrome浏览器中免费实现KeePass密码自动填充 【免费下载链接】ChromeKeePass Chrome extensions for automatically filling credentials from KeePass/KeeWeb 项目地址: https://gitcode.com/gh_mirrors/ch/ChromeKeePass 你是否厌倦了每次登…...