分布式限流

一、核心原理

分布式限流的核心:在集群多台机器上,统一控制总请求速率,而不是每台机器各自限流。

分布式限流核心原理:

  • ① 所有请求共享同一个计数器 / 令牌桶
  • ② 计数必须原子化(多线程 / 多机器不冲突)
  • ③ 统一存储:Redis(最主流)
  • ④ 执行必须高效:用 Lua 脚本保证原子性

一句话总结: Redis + Lua 脚本 = 分布式限流标准方案

二、最常用的 3 种实现方式

1. Redis + Lua(固定窗口限流,最简单通用)

Lua 复制代码
-- key:限流key(如接口名/用户ID)
-- max:最大允许数
-- ttl:时间窗口(秒)
local count = redis.call("incr", KEYS[1])
if count == 1 then
    redis.call("expire", KEYS[1], ARGV[1])
end
if count > tonumber(ARGV[2]) then
    return 0  -- 超过限流,拒绝
end
return 1      -- 放行

原理:

  • 单位时间(如 1 秒)最多允许 N 个请求
  • 用 Redis 做全局计数
  • Lua 脚本保证:判断 + 计数 + 过期 原子执行,无并发问题

优点:实现最简单、性能极高

适用:绝大多数接口限流、网关限流、IP 限流

2. Redis + Lua(令牌桶限流,支持突发流量)

原理:

  • 桶里固定容量令牌
  • 每秒固定放入 N 个令牌
  • 请求拿走一个令牌,没有就拒绝

适用:电商、秒杀、允许瞬时流量突增

3. 成熟框架(不用写代码,直接集成)

如果不想写 Redis+Lua,直接用现成框架:

1) Sentinel(阿里出品,推荐)
  • 原理:默认「滑动窗口」,同时支持令牌桶、漏桶
  • 位置:服务内部(资源层),可在网关、业务接口、方法、热点参数上使用Sentinel。
  • 粒度:细粒度,资源(接口 / 方法)、QPS、并发线程、热点参数、链路 / 关联限流。
  • 目的:服务级精准防护、熔断降级、流量塑形
  • 依赖:单机可独立运行,分布式可结合 Redis/Nacos 等。
2) Spring Cloud Gateway
  • 原理:Redis 存令牌(固定用「令牌桶」),按速率生成,桶有容量,允许一定突发。
  • 位置:网关层(入口),所有请求先到网关。
  • 粒度:粗粒度,按路由 / 接口 / IP / 用户限流。
  • 目的:全局流量削峰、挡大流量、保护整个微服务集群
  • 依赖:必须配合 Redis + Lua 做分布式计数。
Lua 复制代码
--yaml文件
filters:
  - name: RequestRateLimiter
    args:
      redis-rate-limiter.replenishRate: 10  # 每秒生成10个
      redis-rate-limiter.burstCapacity: 20 # 桶最大20个
3) Redisson
  • Redis 官方推荐的 Java 客户端,轻松实现分布式锁 + 分布式限流 + 高并发可靠性
  • 自带 RRateLimiter
  • 一行代码实现分布式限流
java 复制代码
public boolean tryAccess() {
    // 限流 key
    RRateLimiter rateLimiter = redissonClient.getRateLimiter("limit:api:getOrder");

    // 规则:每秒生成 10 个令牌
    rateLimiter.trySetRate(RateType.OVERALL, 10, 1, RateIntervalUnit.SECONDS);

    // 尝试获取 1 个令牌
    return rateLimiter.tryAcquire(1);
}

三、关键点

  • 为什么必须用 Lua? 避免多机并发导致计数不准,保证原子性。

  • 为什么用 Redis? 高性能、内存操作、集群统一计数。

  • 固定窗口 vs 滑动窗口

    • 固定窗口:简单,但临界值可能突刺
    • 滑动窗口:更平滑,适合严格限流
  • 分布式限流一定放在哪里? 网关层(Gateway/Nginx) 统一控制,不要每个服务自己实现。

相关推荐
唐青枫8 小时前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马9 小时前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户3721574261359 小时前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java
用户3721574261359 小时前
Java 打印 Word 文档:从基础打印到高级设置
java
用户3521802454751 天前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程
东坡白菜1 天前
破局全栈:一个前端开发的Java入门实战记录(1)
java·全栈
唐青枫1 天前
Java Tomcat 实战指南:从 Servlet 容器到 Spring Boot 部署
java
wsaaaqqq1 天前
roudan:自由选择实体、灵活操作数据、快速写入数据库的 Java 框架
java
plainGeekDev1 天前
null 判断 → Kotlin 可空类型
android·java·kotlin
糖拌西瓜皮1 天前
Java开发者视角:深入理解Node.js异步编程模型
java·后端·node.js