目录
一、先定义问题:限流究竟要保护什么
(一)限流的本质是受约束的资源分配
(二)必须区分速率、并发量与工作成本
1、速率限制解决“单位时间进入多少”
2、并发限制解决“此刻同时处理多少”
3、队列限制解决“允许等待多少”
(三)容量边界不是一个永久常数
1、静态容量来自压测,不来自经验拍脑袋
2、动态容量会被实例数、命中率与依赖状态改变
3、限流不能替代容量建设
二、经典算法:没有“最好”,只有适配的误差模型
(一)固定窗口计数器:简单但有边界突刺
(二)滑动窗口日志:精确的代价是状态随流量增长
1、算法过程
2、适用与风险
(三)滑动窗口计数器:用可控误差换取固定空间
1、两窗口加权近似
2、分片窗口与误差选择
(四)令牌桶:同时表达平均速率与突发预算
1、两个核心参数
2、参数如何从业务语言推导
2.1 用稳态容量确定补充速率
2.2 用可吸收工作量确定桶容量
2.3 用任意时间区间验证最坏上界
3、多成本请求与退款
(五)漏桶:强调稳定输出而非保留突发
(六)并发限制:处理慢请求、锁竞争和长尾
1、固定并发上限
2、自适应并发
(七)算法选型表
三、从单机到分布式:状态放在哪里决定了系统性质
(一)本地限流:低延迟、高可用,但总量随实例变化
1、本地令牌桶的优势
2、扩缩容造成总配额漂移
3、超卖是可用性与精度之间的主动选择
(二)集中式限流:统一配额与一致决策
1、Redis 模式
2、时间源与时钟漂移
3、Redis Cluster 的键设计
(三)专用限流服务:把策略从数据面抽离
(四)混合架构:近端保护与全局公平同时存在
四、限流键与配额模型:错误维度会比错误算法更危险
(一)先决定“谁”在消耗“什么”
1、主体维度
2、资源维度
3、层级配额
(二)高基数、热点与内存生命周期
1、键数量必须可估算
2、TTL 既是清理机制也是时间语义
3、热点键要从架构上消除
(三)公平性比“总量不超”更难
1、避免大象流挤压小流
2、优先级必须与资源预留绑定
3、配额与商业权益要分离“承诺”和“突发”
五、Redis 令牌桶实现:原子性只是起点
(一)一段可用于工程化改造的 Lua 核心
(二)实现中容易被忽略的七个细节
1、校验参数并限制脚本工作量
2、使用 EVALSHA 并处理脚本缓存丢失
3、连接池超时要小于业务超时
4、客户端重试会重复消耗
5、数值精度要与业务匹配
6、规则变更需要状态迁移语义
7、返回值必须支持客户端正确行为
六、执行策略:拒绝、等待、降级还是转异步
(一)四种动作有不同的成本曲线
1、立即拒绝
2、短暂等待
3、功能降级
4、转异步
(二)响应协议要阻止“重试风暴”
1、Retry-After 与随机退避
2、只重试可重试操作
3、向用户解释限制而非暴露实现
七、故障策略:限流系统本身失效时怎么办
(一)Fail-open 与 fail-closed 没有全局答案
1、开放通过保护可用性
2、关闭通过保护资源与合规
3、按维度设策略
(二)防止治理组件成为新单点
(三)限流与熔断、超时、隔离的协同
八、可观测性与验证:没有证据的限流只是猜测
(一)指标要能回答五个问题
1、谁被限制了
2、为什么被限制
3、限制是否保护了资源
4、用户体验损失多大
5、限流组件是否健康
(二)日志、追踪与基数控制
(三)上线前的四类测试
1、算法确定性测试
2、并发与原子性测试
3、真实流量形状压测
4、故障注入
九、灰度发布与动态调参:把规则当作代码治理
(一)规则生命周期
(二)自动调参要慢于系统变化
(三)容量分配与扩缩容要联动但不能互相追赶
十、一个电商大促案例:从容量数据倒推出组合限流
(一)背景与目标
(二)逐层计算
1、数据库回源预算
2、服务实例自保
3、租户公平
4、物流依赖降级
(三)灰度结果如何判断
十一、进一步思考:把限流扩展成自适应过载治理
(一)从请求数转向“工作量单位”
(二)从统一拒绝转向价值感知调度
(三)从中心真相转向区域自治
(四)从平均容量转向尾部风险预算
(五)从被动防守转向需求整形
十二、落地检查表与结论
(一)设计检查表
(二)核心结论
可参考的文章与文档
干货分享,感谢您的阅读!
限流不是简单地“每秒只放过 N 个请求”,而是一套在容量有限、流量不确定、依赖会失败的现实条件下,持续分配系统处理权的控制机制。本文从容量模型出发,系统比较固定窗口、滑动窗口、令牌桶、漏桶与并发隔离,进一步讨论本地与全局限流、Redis 原子实现、入口与依赖侧的多级防线、优先级与公平性、失败策略、动态配额、可观测性、压测、灰度及事故复盘。
本文尽可能给出可运行代码、参数推导方法与工程检查表,目标是让限流从“一个中间件开关”变成可解释、可验证、可演进的过载治理能力。