欢迎光临
我们一直在努力

Redis分布式限流技术原理与实战

文章目录

    • 一、限流的本质与算法演进
      • 四种经典算法解析
        • 1️⃣ 固定窗口计数器法(Fixed Window Counter)
        • 2️⃣ 滑动窗口法(Sliding Window Log/Counter)
        • 3️⃣ 漏桶算法(Leaky Bucket)
        • 4️⃣ 令牌桶算法(Token Bucket)
    • 二、分层限流架构
      • 三层典型架构
    • 三、工程级方案详解
      • 方案一:Guava 本地令牌桶(单机限流)
      • 方案二:Redis + Lua Script 分布式滑动窗口限流
        • Lua 脚本示例(`sliding_window.lua`)
        • Java 接入示例
        • 时序图说明
      • 方案三:Alibaba Sentinel 微服务限流
    • 四、方案对比与选型建议
    • 五、实战优化与注意事项
      • 限流维度建议
      • 限流之后的应对策略
      • 多级限流策略(热点Key优化)
    • 六、总结

一、限流的本质与算法演进

在高并发系统中,限流(Rate Limiting) 是应对突发流量、保护下游系统资源的核心手段之一。 限流的目的是在保证系统可用性的前提下,平滑地削峰填谷。

  • 核心算法思维导图:

#mermaid-svg-92AYjg21AJiSnGh8{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-92AYjg21AJiSnGh8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-92AYjg21AJiSnGh8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-92AYjg21AJiSnGh8 .error-icon{fill:#552222;}#mermaid-svg-92AYjg21AJiSnGh8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-92AYjg21AJiSnGh8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-92AYjg21AJiSnGh8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-92AYjg21AJiSnGh8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-92AYjg21AJiSnGh8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-92AYjg21AJiSnGh8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-92AYjg21AJiSnGh8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-92AYjg21AJiSnGh8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-92AYjg21AJiSnGh8 .marker.cross{stroke:#333333;}#mermaid-svg-92AYjg21AJiSnGh8 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-92AYjg21AJiSnGh8 p{margin:0;}#mermaid-svg-92AYjg21AJiSnGh8 .edge{stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .section–1 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section–1 path,#mermaid-svg-92AYjg21AJiSnGh8 .section–1 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section–1 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section–1 text{fill:#ffffff;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth–1{stroke-width:17;}#mermaid-svg-92AYjg21AJiSnGh8 .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-0 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-0 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-0 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-0 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-0 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-0{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-0{stroke-width:14;}#mermaid-svg-92AYjg21AJiSnGh8 .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-1 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-1 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-1 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-1 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-1 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-1{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-1{stroke-width:11;}#mermaid-svg-92AYjg21AJiSnGh8 .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-2 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-2 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-2 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-2 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-2 text{fill:#ffffff;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-2{stroke-width:8;}#mermaid-svg-92AYjg21AJiSnGh8 .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-3 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-3 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-3 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-3 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-3 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-3{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-3{stroke-width:5;}#mermaid-svg-92AYjg21AJiSnGh8 .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-4 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-4 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-4 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-4 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-4 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-4{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-4{stroke-width:2;}#mermaid-svg-92AYjg21AJiSnGh8 .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-5 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-5 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-5 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-5 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-5 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-5{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-5{stroke-width:-1;}#mermaid-svg-92AYjg21AJiSnGh8 .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-6 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-6 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-6 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-6 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-6 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-6{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-6{stroke-width:-4;}#mermaid-svg-92AYjg21AJiSnGh8 .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-7 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-7 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-7 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-7 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-7 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-7{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-7{stroke-width:-7;}#mermaid-svg-92AYjg21AJiSnGh8 .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-8 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-8 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-8 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-8 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-8 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-8{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-8{stroke-width:-10;}#mermaid-svg-92AYjg21AJiSnGh8 .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-9 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-9 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-9 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-9 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-9 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-9{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-9{stroke-width:-13;}#mermaid-svg-92AYjg21AJiSnGh8 .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-10 rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-10 path,#mermaid-svg-92AYjg21AJiSnGh8 .section-10 circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-10 polygon,#mermaid-svg-92AYjg21AJiSnGh8 .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-10 text{fill:black;}#mermaid-svg-92AYjg21AJiSnGh8 .node-icon-10{font-size:40px;color:black;}#mermaid-svg-92AYjg21AJiSnGh8 .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .edge-depth-10{stroke-width:-16;}#mermaid-svg-92AYjg21AJiSnGh8 .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled,#mermaid-svg-92AYjg21AJiSnGh8 .disabled circle,#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:lightgray;}#mermaid-svg-92AYjg21AJiSnGh8 .disabled text{fill:#efefef;}#mermaid-svg-92AYjg21AJiSnGh8 .section-root rect,#mermaid-svg-92AYjg21AJiSnGh8 .section-root path,#mermaid-svg-92AYjg21AJiSnGh8 .section-root circle,#mermaid-svg-92AYjg21AJiSnGh8 .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-92AYjg21AJiSnGh8 .section-root text{fill:#ffffff;}#mermaid-svg-92AYjg21AJiSnGh8 .section-root span{color:#ffffff;}#mermaid-svg-92AYjg21AJiSnGh8 .section-2 span{color:#ffffff;}#mermaid-svg-92AYjg21AJiSnGh8 .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-92AYjg21AJiSnGh8 .edge{fill:none;}#mermaid-svg-92AYjg21AJiSnGh8 .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-92AYjg21AJiSnGh8 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

限流核心算法

Fixed Window Counter

简单实现

存在毛刺问题

Sliding Window

平滑控制

Redis ZSet实现

Leaky Bucket

输出速率恒定

平滑突发流量

Token Bucket

定期发放令牌

支持突发流量


四种经典算法解析

1️⃣ 固定窗口计数器法(Fixed Window Counter)

原理: 在固定时间窗口内统计请求总数,当超过阈值后拒绝请求。

优点: 简单易实现 缺点: 临界区间可能出现突发流量 (“毛刺”)

2️⃣ 滑动窗口法(Sliding Window Log/Counter)

原理: 将时间等分为若干小窗口,随着时间推进不断滑动删除过期记录。

优点: 精度高、流量分布更均匀 缺点: 统计基于历史记录,略有性能消耗

3️⃣ 漏桶算法(Leaky Bucket)

原理: 请求流如同水流进桶,桶底以固定速率漏水(处理请求),超出部分直接溢出。

特点: 输出速率稳定,强制限速

4️⃣ 令牌桶算法(Token Bucket)

原理: 系统按固定速率生成令牌放入桶中,请求需消耗令牌才能处理。

特点: 支持一定程度的突发流量,互联网高并发限流首选。


二、分层限流架构

限流既有“地面防线”(应用层),也有“网络关卡”(网关层),多层协同构成系统保护伞。

#mermaid-svg-wP0bWhahcNl8yPzo{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wP0bWhahcNl8yPzo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wP0bWhahcNl8yPzo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wP0bWhahcNl8yPzo .error-icon{fill:#552222;}#mermaid-svg-wP0bWhahcNl8yPzo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wP0bWhahcNl8yPzo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wP0bWhahcNl8yPzo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wP0bWhahcNl8yPzo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wP0bWhahcNl8yPzo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wP0bWhahcNl8yPzo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wP0bWhahcNl8yPzo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wP0bWhahcNl8yPzo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wP0bWhahcNl8yPzo .marker.cross{stroke:#333333;}#mermaid-svg-wP0bWhahcNl8yPzo svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wP0bWhahcNl8yPzo p{margin:0;}#mermaid-svg-wP0bWhahcNl8yPzo .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-wP0bWhahcNl8yPzo .cluster-label text{fill:#333;}#mermaid-svg-wP0bWhahcNl8yPzo .cluster-label span{color:#333;}#mermaid-svg-wP0bWhahcNl8yPzo .cluster-label span p{background-color:transparent;}#mermaid-svg-wP0bWhahcNl8yPzo .label text,#mermaid-svg-wP0bWhahcNl8yPzo span{fill:#333;color:#333;}#mermaid-svg-wP0bWhahcNl8yPzo .node rect,#mermaid-svg-wP0bWhahcNl8yPzo .node circle,#mermaid-svg-wP0bWhahcNl8yPzo .node ellipse,#mermaid-svg-wP0bWhahcNl8yPzo .node polygon,#mermaid-svg-wP0bWhahcNl8yPzo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wP0bWhahcNl8yPzo .rough-node .label text,#mermaid-svg-wP0bWhahcNl8yPzo .node .label text,#mermaid-svg-wP0bWhahcNl8yPzo .image-shape .label,#mermaid-svg-wP0bWhahcNl8yPzo .icon-shape .label{text-anchor:middle;}#mermaid-svg-wP0bWhahcNl8yPzo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wP0bWhahcNl8yPzo .rough-node .label,#mermaid-svg-wP0bWhahcNl8yPzo .node .label,#mermaid-svg-wP0bWhahcNl8yPzo .image-shape .label,#mermaid-svg-wP0bWhahcNl8yPzo .icon-shape .label{text-align:center;}#mermaid-svg-wP0bWhahcNl8yPzo .node.clickable{cursor:pointer;}#mermaid-svg-wP0bWhahcNl8yPzo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wP0bWhahcNl8yPzo .arrowheadPath{fill:#333333;}#mermaid-svg-wP0bWhahcNl8yPzo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wP0bWhahcNl8yPzo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wP0bWhahcNl8yPzo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wP0bWhahcNl8yPzo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wP0bWhahcNl8yPzo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wP0bWhahcNl8yPzo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wP0bWhahcNl8yPzo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wP0bWhahcNl8yPzo .cluster text{fill:#333;}#mermaid-svg-wP0bWhahcNl8yPzo .cluster span{color:#333;}#mermaid-svg-wP0bWhahcNl8yPzo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wP0bWhahcNl8yPzo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wP0bWhahcNl8yPzo rect.text{fill:none;stroke-width:0;}#mermaid-svg-wP0bWhahcNl8yPzo .icon-shape,#mermaid-svg-wP0bWhahcNl8yPzo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wP0bWhahcNl8yPzo .icon-shape p,#mermaid-svg-wP0bWhahcNl8yPzo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wP0bWhahcNl8yPzo .icon-shape rect,#mermaid-svg-wP0bWhahcNl8yPzo .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wP0bWhahcNl8yPzo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wP0bWhahcNl8yPzo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wP0bWhahcNl8yPzo :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

网络入口

网关层限流 Nginx/OpenResty

分布式限流 Redis + Lua

应用层限流 Sentinel/Guava

业务处理与降级

三层典型架构

层级技术栈核心用途
网关层 Nginx / OpenResty / Kong 拦截恶意流量、防DDoS
分布式中间层 Redis + Lua / Redisson 统一全局限流、原子操作
应用层 Guava / Sentinel 微服务保护、错误隔离

三、工程级方案详解

方案一:Guava 本地令牌桶(单机限流)

import com.google.common.util.concurrent.RateLimiter;

public class LocalLimitService {

// 每秒生成 5 个令牌
private final RateLimiter rateLimiter = RateLimiter.create(5.0);

public void accessApi() {
if (rateLimiter.tryAcquire()) {
System.out.println("请求成功,执行业务逻辑");
} else {
System.out.println("限流中,请稍后再试");
throw new RuntimeException("Too Many Requests");
}
}
}

适用场景: 非分布式系统、小型服务限流。


方案二:Redis + Lua Script 分布式滑动窗口限流

思路: 利用 Redis 的 ZSet 数据结构,将请求时间戳记录为 score,实现可滑动的时间窗口统计。

Lua 脚本示例(sliding_window.lua)

— KEYS[1]: 限流Key
— ARGV[1]: 窗口时间 (毫秒)
— ARGV[2]: 当前时间 (毫秒)
— ARGV[3]: 阈值(最大请求数)

local key = KEYS[1]
local window_size = tonumber(ARGV[1])
local now = tonumber(ARGV[2])
local limit = tonumber(ARGV[3])

— 1. 移除过期数据
redis.call('ZREMRANGEBYSCORE', key, 0, now window_size)

— 2. 查看当前计数
local current_count = redis.call('ZCARD', key)

— 3. 判断是否超限
if current_count < limit then
redis.call('ZADD', key, now, now .. "-" .. math.random(10000))
redis.call('PEXPIRE', key, window_size + 1000)
return 1
else
return 0
end

Java 接入示例

public boolean allowRequest(String key, int limit, long windowMillis) {
String script = loadLuaScript("sliding_window.lua");
long now = System.currentTimeMillis();

Object result = redisTemplate.execute(
new DefaultRedisScript<>(script, Long.class),
Collections.singletonList(key),
windowMillis, now, limit
);
return (Long) result == 1;
}

时序图说明

Redis

Server

Client

Redis

Server

Client

#mermaid-svg-stWrDFw5IE96dHeL{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-stWrDFw5IE96dHeL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-stWrDFw5IE96dHeL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-stWrDFw5IE96dHeL .error-icon{fill:#552222;}#mermaid-svg-stWrDFw5IE96dHeL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-stWrDFw5IE96dHeL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-stWrDFw5IE96dHeL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-stWrDFw5IE96dHeL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-stWrDFw5IE96dHeL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-stWrDFw5IE96dHeL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-stWrDFw5IE96dHeL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-stWrDFw5IE96dHeL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-stWrDFw5IE96dHeL .marker.cross{stroke:#333333;}#mermaid-svg-stWrDFw5IE96dHeL svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-stWrDFw5IE96dHeL p{margin:0;}#mermaid-svg-stWrDFw5IE96dHeL .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-stWrDFw5IE96dHeL text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-stWrDFw5IE96dHeL .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-stWrDFw5IE96dHeL .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-stWrDFw5IE96dHeL .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-stWrDFw5IE96dHeL .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-stWrDFw5IE96dHeL #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-stWrDFw5IE96dHeL .sequenceNumber{fill:white;}#mermaid-svg-stWrDFw5IE96dHeL #sequencenumber{fill:#333;}#mermaid-svg-stWrDFw5IE96dHeL #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-stWrDFw5IE96dHeL .messageText{fill:#333;stroke:none;}#mermaid-svg-stWrDFw5IE96dHeL .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-stWrDFw5IE96dHeL .labelText,#mermaid-svg-stWrDFw5IE96dHeL .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-stWrDFw5IE96dHeL .loopText,#mermaid-svg-stWrDFw5IE96dHeL .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-stWrDFw5IE96dHeL .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-stWrDFw5IE96dHeL .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-stWrDFw5IE96dHeL .noteText,#mermaid-svg-stWrDFw5IE96dHeL .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-stWrDFw5IE96dHeL .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-stWrDFw5IE96dHeL .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-stWrDFw5IE96dHeL .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-stWrDFw5IE96dHeL .actorPopupMenu{position:absolute;}#mermaid-svg-stWrDFw5IE96dHeL .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-stWrDFw5IE96dHeL .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-stWrDFw5IE96dHeL .actor-man circle,#mermaid-svg-stWrDFw5IE96dHeL line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-stWrDFw5IE96dHeL :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

alt

[允许]

[超限]

请求API

执行Lua限流脚本

返回是否允许(1/0)

业务正常响应

返回 HTTP 429

优点:

  • 原子操作(Lua脚本执行不可分割)
  • 精确控制时间窗口
  • 支持分布式水平扩展

方案三:Alibaba Sentinel 微服务限流

优势:

  • 提供完善的控制台
  • 支持热点参数限流、链路限流
  • 可与 Nacos/Apollo 动态配置联动

@SentinelResource(value = "createOrder", blockHandler = "handleBlock")
public String createOrder(String orderId) {
return "订单创建成功: " + orderId;
}

public String handleBlock(String orderId, BlockException ex) {
return "系统繁忙,请稍后再试 (限流)";
}

规则配置:

  • QPS 阈值:10
  • 流控模式:直接
  • 控制效果:快速失败

四、方案对比与选型建议

场景推荐方案优势典型技术
单机任务或测试环境 Guava RateLimiter 简单可靠 Java
Web 集群统一限流 Redis + Lua 支持多节点同步限流 Redis
微服务架构 Sentinel 丰富策略&可视化 Spring Cloud

五、实战优化与注意事项

限流维度建议

限流维度使用场景示例
按 IP 防爬虫 / DDoS limit:ip:192.168.0.1
按用户ID 防止账号刷接口 limit:user:1001
按 API 路径 保护热点接口 limit:api:/order/create
按参数 热点商品限流 limit:goods:sku123

限流之后的应对策略

  • HTTP 429 返回(Too Many Requests)
  • 进入消息队列(MQ)排队处理
  • 返回缓存结果或默认值(降级)
  • #mermaid-svg-mYjIc56c9jQbGKew{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mYjIc56c9jQbGKew .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mYjIc56c9jQbGKew .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mYjIc56c9jQbGKew .error-icon{fill:#552222;}#mermaid-svg-mYjIc56c9jQbGKew .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mYjIc56c9jQbGKew .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mYjIc56c9jQbGKew .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mYjIc56c9jQbGKew .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mYjIc56c9jQbGKew .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mYjIc56c9jQbGKew .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mYjIc56c9jQbGKew .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mYjIc56c9jQbGKew .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mYjIc56c9jQbGKew .marker.cross{stroke:#333333;}#mermaid-svg-mYjIc56c9jQbGKew svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mYjIc56c9jQbGKew p{margin:0;}#mermaid-svg-mYjIc56c9jQbGKew .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-mYjIc56c9jQbGKew .cluster-label text{fill:#333;}#mermaid-svg-mYjIc56c9jQbGKew .cluster-label span{color:#333;}#mermaid-svg-mYjIc56c9jQbGKew .cluster-label span p{background-color:transparent;}#mermaid-svg-mYjIc56c9jQbGKew .label text,#mermaid-svg-mYjIc56c9jQbGKew span{fill:#333;color:#333;}#mermaid-svg-mYjIc56c9jQbGKew .node rect,#mermaid-svg-mYjIc56c9jQbGKew .node circle,#mermaid-svg-mYjIc56c9jQbGKew .node ellipse,#mermaid-svg-mYjIc56c9jQbGKew .node polygon,#mermaid-svg-mYjIc56c9jQbGKew .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mYjIc56c9jQbGKew .rough-node .label text,#mermaid-svg-mYjIc56c9jQbGKew .node .label text,#mermaid-svg-mYjIc56c9jQbGKew .image-shape .label,#mermaid-svg-mYjIc56c9jQbGKew .icon-shape .label{text-anchor:middle;}#mermaid-svg-mYjIc56c9jQbGKew .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mYjIc56c9jQbGKew .rough-node .label,#mermaid-svg-mYjIc56c9jQbGKew .node .label,#mermaid-svg-mYjIc56c9jQbGKew .image-shape .label,#mermaid-svg-mYjIc56c9jQbGKew .icon-shape .label{text-align:center;}#mermaid-svg-mYjIc56c9jQbGKew .node.clickable{cursor:pointer;}#mermaid-svg-mYjIc56c9jQbGKew .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mYjIc56c9jQbGKew .arrowheadPath{fill:#333333;}#mermaid-svg-mYjIc56c9jQbGKew .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mYjIc56c9jQbGKew .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mYjIc56c9jQbGKew .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mYjIc56c9jQbGKew .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mYjIc56c9jQbGKew .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mYjIc56c9jQbGKew .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mYjIc56c9jQbGKew .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mYjIc56c9jQbGKew .cluster text{fill:#333;}#mermaid-svg-mYjIc56c9jQbGKew .cluster span{color:#333;}#mermaid-svg-mYjIc56c9jQbGKew div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mYjIc56c9jQbGKew .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mYjIc56c9jQbGKew rect.text{fill:none;stroke-width:0;}#mermaid-svg-mYjIc56c9jQbGKew .icon-shape,#mermaid-svg-mYjIc56c9jQbGKew .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mYjIc56c9jQbGKew .icon-shape p,#mermaid-svg-mYjIc56c9jQbGKew .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mYjIc56c9jQbGKew .icon-shape rect,#mermaid-svg-mYjIc56c9jQbGKew .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mYjIc56c9jQbGKew .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mYjIc56c9jQbGKew .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mYjIc56c9jQbGKew :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    可降级

    异步削峰

    请求流入

    是否限流?

    正常处理

    返回429

    返回缓存/默认响应

    进入消息队列排队


    多级限流策略(热点Key优化)

    分布式限流在极端高并发场景下可能导致 Redis 热点。 ✅ 建议方案:本地缓存 + Redis 双层限流。

    – 本地限流 80% 请求
    – Redis 限流校验剩余 20%


    六、总结

    🔹 限流是高可用系统的“安全阀”,能有效削峰、保护服务稳定。 🔹 Redis 限流凭借其高性能、原子操作特性,是业界最常用的分布式限流手段。 🔹 最佳实践:

    网关限流兜底 + Redis 全局限流 + 应用层防御 打造“外防恶流、内稳业务”的坚固防线。

    赞(0)
    未经允许不得转载:171主机测评 » Redis分布式限流技术原理与实战
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址