在Spring Boot中如何使用Redis实现滑动窗口限流算法?

落宇大大_4158

落宇大大_4158

2026-11-04

272人浏览

原创

滑动窗口限流必须用Lua脚本原子执行ZREMRANGEBYSCORE清理、ZCARD统计、ZADD插入三步,因INCR+EXPIRE非原子易致漏限、误限及永久key残留;ZSET是唯一合理选择,支持毫秒级时间戳score区间操作,确保动态时间窗口精度。

在spring boot中如何使用redis实现滑动窗口限流算法?

滑动窗口限流不能靠 INCR + EXPIRE 拼凑,否则必然出现漏限、误限、数据永久残留等问题;必须用 Lua 脚本在 Redis 服务端原子执行「清理过期时间戳 → 统计当前数量 → 插入新时间戳」三步。

为什么 ZSET 是滑动窗口的唯一合理选择

滑动窗口的本质是「任意时间点往前推 N 秒内请求数 ≤ 阈值」,这要求能按时间范围精确筛选和计数。只有 ZSET 支持基于 score(毫秒时间戳)做区间操作:

  • ZREMRANGEBYSCORE key 0 (now_ms - window_ms) 可一次性剔除所有过期时间戳
  • ZCARD key 直接返回当前窗口内有效请求数,不依赖客户端计数
  • ZADD key now_ms now_ms 插入新请求,member 复用 score 节省内存,避免 UUID 或随机字符串

用 String + INCR 只能实现固定窗口,且无法区分「第 59 秒的请求」和「第 1 秒的请求」;用 LIST 则需客户端拉取全部元素再过滤,网络和 CPU 开销大,且无法原子化。

Lua 脚本必须传入服务端时间戳,不能用 Redis 的 TIME 命令

脚本里 now_ms 必须由 Java 侧调用 System.currentTimeMillis() 传入,而不是在 Lua 中执行 redis.call('TIME'):

  • TIME 在 Redis 集群中各节点返回值可能不同(时钟漂移),导致窗口边界错乱
  • 客户端传入时间虽有网络延迟,但误差在毫秒级,远小于典型窗口(如 60 秒),可接受
  • 脚本中所有时间比较都基于同一基准,避免跨节点时间不一致引发的统计偏差

示例关键行:local now_ms = tonumber(ARGV[3]),对应 Java 调用时第三个参数填 System.currentTimeMillis()。

Sentinal Redis
Sentinal Redis

监控Redis服务器健康状况、内存、性能及BullMQ队列。检查队列深度、失败任务,分析慢查询并诊断问题。

下载

Spring Boot 中必须预加载 Lua 脚本 SHA1,禁用每次传字符串

别用 StringRedisTemplate.eval() 直接传脚本源码,会触发 Redis 重复编译、SHA1 计算和网络传输开销,压测时 QPS 直降 30%+:

  • 启动时用 RedisScript 加载脚本并缓存其 SHA1 值
  • 运行时统一调用 redisTemplate.execute(RedisScript, keys, args...)
  • KEYS[1] 必须带业务维度前缀,比如 "rate_limit:uid:" + userId,防止不同用户共用 key 导致误限

错误示范:template.eval("return redis.call('ZCARD', KEYS[1])", ...);正确做法是把完整脚本存在 sliding_window.lua 文件中,用 ResourceLoader 读取后注册为 DefaultRedisScript Bean。

容易被忽略的三个生产细节

这三个点线上最容易出问题,但文档几乎不提:

  • Redis 连接池要调大:限流是高频小请求,lettuce.pool.max-active 至少设为 16,否则连接争抢导致限流判断超时失败
  • ZSET 不清空会持续膨胀:脚本里 ZREMRANGEBYSCORE 后没做 ZCARD == 0 判断,key 会长期存在;建议加一句 if redis.call('ZCARD', key) == 0 then redis.call('DEL', key) end
  • 降级开关必须有:Redis 故障时不能直接放行,应 fallback 到本地 Guava RateLimiter(按实例维度保底),避免雪崩

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

redis spring boot

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2025.08.06

2811

22

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

2026.01.26

517

25

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

2023.08.14

6636

4

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4789

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

4355

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

8312

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

663

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

776

6

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

8502

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习