Redis漏斗限流实现与优化策略,redis限流器怎么配置,漏斗算法在高并发场景如何应用

文章导读
Redis 漏斗限流实现主要基于固定速率流出请求的原理,通过 Redis 计数器或列表模拟漏斗容量与流出速率。配置限流器时需设定关键参数如桶容量、流出速率及时间窗口,并利用 Redis 的原子操作(如 incr 或 Lua 脚本)确保高并发下的准确性。在高并发场景中,应用漏斗算法可有效平滑流量突刺,保护后端服务稳定,但需注意锁竞争问题,可通过优化键值设计或采用 Redis-cell 模块来提升性能
📋 目录
  1. 基于 redis 实现分布式服务限流器
  2. Redis 之限流
  3. 实战案例分析:使用 Redis 实现一个 API 的限流保护
  4. 太优雅了!用 Redis 高效实现限流功能!
  5. FAQ
A A

Redis 漏斗限流实现主要基于固定速率流出请求的原理,通过 Redis 计数器或列表模拟漏斗容量与流出速率。配置限流器时需设定关键参数如桶容量、流出速率及时间窗口,并利用 Redis 的原子操作(如 incr 或 Lua 脚本)确保高并发下的准确性。在高并发场景中,应用漏斗算法可有效平滑流量突刺,保护后端服务稳定,但需注意锁竞争问题,可通过优化键值设计或采用 Redis-cell 模块来提升性能与稳定性,同时结合监控动态调整阈值以实现最佳限流效果。

基于 redis 实现分布式服务限流器

在后台开发中,服务端的限流器是一个很常见并且十分有用的组件,利用好限流器可以限制请求速率,保护后台服务。比较常见的限流器分为两种,漏桶算法和令牌桶算法。漏桶算法 漏桶算法原理很简单,用一个漏斗来控制请求的速率。在漏斗上方是收到的所有请求,请求就像水一样会进入漏斗中,同时漏斗也会以恒定的速度将水 (请求) 从下方进行排出,被排出的水 (请求) 才能访问服务。当请求量不大时候,如进水速率 < 出水速率那么其实漏斗并没有起到作用;当请求量很大的时候,超过漏斗容量的请求将被溢出,并且出水口可以一直保证恒定的速率。令牌桶算法 令牌桶算法原理也很简单,假设我们的服务允许请求速度上限为 5000 次/分,那么这就意味着桶内的令牌数为 5000,并且每隔一分钟桶内的令牌数就会被重置为 5000。每一个请求过来都需要从桶内拿一块令牌,如果能取得令牌则允许访问服务,否则将会拒绝请求。基于 redis 的分布式服务限流器 本文将基于 redis 来设计一个在分布式场景下的令牌桶算法,旨在重点解决以下问题:并发请求如何处理?何时进行加锁?何时不需要加锁?如何提高准确性和稳定性?流程图 详细设计 在实际场景中,服务的限流往往会和一些参数绑定在一起,比如:限制同一个 ip 地址的请求速率为 5000 次/分,限制某一个业务 id 的请求速率为 5000 次/分,根据这些绑定的变量数值,我们可以在 redis 中设置对应的 key,通过不断累加该 key 对应的数值来实现限流器的设计。计数器初始化 假设我们服务请求速率的最大值 max 为 5000 次/分。当服务器收到请求时,首先判断 redis 中对应键 k 的数值 v 是否超过 5000,如果是则拒绝请求,如果为否则继续判断 v 是否为 0,当 v 为 0 的时候,我们需要进行初始化。初始化需要将 v 的值置为 1,并且设置过期时间为 60s。考虑以下几个问题:初始化是否需要加锁?为什么不能直接用 incr 命令?对于第一个问题,答案肯定是必然的,我们需要保证只有一个请求能进行初始化,否则在并发情况下会出现多个请求线程都对 v 进行置 1 操作,从而导致计数器不准确。(消息于 2026 年 4 月 11 日发布)

Redis 之限流

当系统的处理能力有限时,如何阻止计划外的请求继续对系统施压,是一个需要重视的问题,避免超出负载的流量影响系统的稳定运行,这就需要用到限流算法,除了控制流量,限流还有一个目的是控制用户行为,避免垃圾请求,比如在论坛上,用户的发帖、回复、点赞等行为都要严格受控,一般短时间内用户的请求将会收到一定次数的限制,超过这个限制将拒绝或做其它处理。使用 redis 简单限流 接下来我们使用 redis 实现一个在指定时间内只能做固定次数的操作,超出这个次数,就做出拒绝处理,我们可以考虑使用 zset 这个数据结构,使用 score 存储每次操作的时间戳,value 根据业务情况来,保证 value 唯一性即可,随后每次我们使用滑动时间窗口 (定宽),每次都保留着这个窗口内的数据,其余的都 trim 掉,此举也可避免一定的内存空间的浪费,如果用户是冷用户,滑动时间窗口内的行为是空记录,那么该 zset 就可以从内存中移除,不再占用空间,使用 zset 结构记录用户的行为历史,每一个行为都会作为 zset 中的一个 key 保存下来,同一个用户的同一种行为用一个 zset 记录,下方使用 zset 的滑动窗口代码实现,我们首先在 zset 中添加用户本次行为,然后删除了本次时间窗口外的数据,最后获取本次窗口内的数据总数,如果总数没有超出限制,我们返回 true,超出限制了返回 false,下面 main 方法中设置的时间窗口是 60s,在 60s 內最多 5 次請求,根据结果我们可以看到,循环 20 次,只有前 5 次得到了 true,允许请求访问,后续的结果全是 false,被拒绝访问。因为这几个连续的操作都是针对同一个 key 的,使用 pipeline 可以显著提高 redis 存取效率。不过这种方案存在着自己的不足,因为要记录时间窗口内所有的行为记录,如果这个量很大,比如 60s 内操作不能超过 100 万次,这时候是不适合用这种方式的,会消耗大量的存储空间。漏斗限流 漏斗限流是最常用的限流方法之一,这个算法的灵感来自于漏斗 (funnel) 的结构,如下图所示,漏斗的容量是有限的,如果将漏嘴堵住,然后一直灌水,它会变满,直到再也装不下,如果将漏嘴放开,水会从下方流出,流走一部分后,又可以继续灌水,如果漏嘴的速率大于灌水的速率,那么漏洞永远装不满,如果漏嘴速率小于灌水的速率,一旦漏斗满了,灌水就需要暂停并等待漏斗腾出一部分的空间,方可继续灌水,所以,漏斗的剩余空间就代表着当前行为可以持续进行的数量,漏嘴的流水速率代表着系统允许该行为的最大频率。(2021 年 12 月 21 日的资料)

实战案例分析:使用 Redis 实现一个 API 的限流保护

一、Redis 在限流中的应用 Redis 在限流中的应用主要基于两种算法:令牌桶算法和漏桶算法。1. 令牌桶算法 令牌桶算法是一种用于控制请求速率的算法。它维护一个固定容量的令牌桶,桶中可以存放一定数量的令牌。在每个时间单位内,新的令牌会按一定的速率添加到桶中。如果一个请求需要处理,就需要从桶中消耗一定数量的令牌。如果桶中没有足够的令牌,则请求将被拒绝。令牌桶算法的优点在于它可以控制请求的速率和延迟,并且可以根据当前的系统负载动态调整请求的处理速率。2. 漏桶算法 漏桶算法是另一种常用的限流算法。它维护一个固定容量的漏桶,定时向漏桶中注入请求,每个请求都从漏桶中流出,当漏桶溢满时,多余的请求将被丢弃或延迟处理。漏桶算法的优点在于它可以平滑请求的流入速率,确保系统的稳定运行。二、限流策略的最佳实践 1. 确定限流策略 业务目标:明确你的业务目标是什么?例如,保护后端服务免受过载影响、防止恶意攻击、保证用户体验等。用户类型:识别不同类型的用户 (例如普通用户、VIP 用户) 并为他们制定不同的限流策略。请求类型:考虑不同类型的请求 (例如读取请求、写入请求) 并为它们设置不同的阈值。时间窗口:确定限流的时间窗口长度,例如一分钟、一小时等。限流单位:确定限流的单位,例如每秒、每分钟、每小时等。2. 配置 Redis 内存大小:确保 Redis 有足够的内存来存储限流相关的数据。持久化设置:根据业务需求决定是否启用持久化,以及使用何种持久化方式。性能优化:调整 Redis 的性能相关设置,如 maxmemory-policy、client-output-buffer-limit 等。连接池:在客户端配置合理的连接池大小,避免频繁建立和销毁连接。3. 限流阈值的动态调整 监控工具:使用监控工具 (如 Prometheus、Grafana) 收集实时性能数据。数据分析:分析收集到的数据,识别系统负载的变化趋势。动态调整:根据分析结果动态调整限流阈值。4. 限流后的反馈 HTTP 状态码:返回 429 Too Many Requests 表示请求过多。错误消息:返回 JSON 格式的错误消息,说明请求被拒绝的原因。重试策略:建议客户端在等待一段时间后再尝试。(搜索结果收录于 2025 年 4 月 16 日)

Redis漏斗限流实现与优化策略,redis限流器怎么配置,漏斗算法在高并发场景如何应用

太优雅了!用 Redis 高效实现限流功能!

漏桶算法 请求被收集到桶中,以固定速率处理。如果输入流量较大,则多余的流量会在桶中缓存起来,直到桶满为止。一旦桶满,新的流量将会被丢弃。优点:平滑处理请求,不受突发流量影响。缺点:处理速度固定,无法充分利用系统资源。适用场景:对处理速度有严格要求,不希望因为流量波动而影响处理速度的系统。令牌桶算法 允许在有可用令牌的情况下以任意速率传输数据。如果有足够的令牌,可以立即处理一个大的流量突发。当流量较小时,令牌可以在桶中积累。如果桶中令牌满了,则新生成的令牌将被丢弃。优点:允许一定程度的突发流量,同时限制长时间内的流量。缺点:实现较为复杂,需要维护令牌生成和消耗。适用场景:需要平衡突发流量和长时间流量限制的系统。滑动窗口限流 相对来说,滑动窗口限流可以更灵活地应对流量波动,是使用的最多的一个,这里介绍用 redis 来实现用户维度或接口维度下该限流的两种方式,可以用 list 或 zset。List 结构 在 Redis 中,可以使用列表 (List) 来存储时间窗口内的请求计数。通过维护多个列表来实现多个时间窗口的计数,然后根据这些计数来判断是否允许新的请求通过。(截至 2024 年 4 月 25 日)

FAQ

漏斗算法和令牌桶算法的主要区别是什么?

Redis漏斗限流实现与优化策略,redis限流器怎么配置,漏斗算法在高并发场景如何应用

漏桶算法以固定速率处理请求,多余流量缓存或丢弃,平滑但不利用突发资源;令牌桶允许突发流量,有令牌即可处理,更灵活。

Redis 限流在高并发下如何保证准确性?

需要使用 Lua 脚本保证原子性,或在初始化计数器时加锁,避免并发下多个线程同时置 1 导致计数器不准确。