缓冲与流量塑形

返回 高并发

数据层外面的缓冲指:在请求进入 MySQL / 核心 Redis 写路径之前,用队列、限流、异步与丢弃策略吸收流量形状。高并发系统里,入口形态往往比数据库选型更决定生死


流量塑形目标

目标手段
削峰队列积压 + 消费者匀速处理
隔离线程池 / 舱壁,慢依赖不拖垮全局
快速失败超限直接 429,保护线程
背压下游慢时上游减速
合并窗口内多次写合并一次

分层缓冲示意

用户
  ▼
[CDN / 静态]           ← 静态资源不进业务
  ▼
[L7 网关 / API Gateway] ← 全局限流、鉴权、WAF
  ▼
[应用接入层]            ← Tomcat 队列、异步 Servlet、本地队列
  ▼
[消息队列]              ← 核心削峰(Kafka / RocketMQ / 内存队列)
  ▼
[聚合 / 计算服务]       ← 合并写、批量刷 Redis
  ▼
[数据层]                ← MySQL / Redis 持久结构

详见 流量入口层API 网关


网关与限流

算法选择

算法特点场景
令牌桶允许一定突发API 全局限流
漏桶输出匀速保护下游固定吞吐
滑动窗口精确计数按用户 / IP 每分钟 N 次
固定窗口实现简单,边界双倍不推荐单独用于资金类
# 示意:Spring Cloud Gateway 限流
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter
# Redis 实现分布式计数

分布式限流需 Redis / 网关集群共享计数器,见 Redis 限流 Lua。

按维度限流

维度示例
全站保护整体
用户 ID防刷、午夜步数上报
接口/report 单独配额
租户SaaS 隔离

应用层缓冲

同步改异步

@PostMapping("/report")
public DeferredResult<ApiResp> report(@RequestBody Req req) {
    DeferredResult<ApiResp> dr = new DeferredResult<>(3000);
    executor.submit(() -> {
        mq.send(req);
        dr.setResult(ApiResp.ok());
    });
    return dr;
}

或:先返回 202 Accepted,客户端轮询 / WebSocket 推送结果。

本地内存队列(轻量削峰)

请求 → LinkedBlockingQueue(有界)
         → 单线程 / 小线程池批量消费 → Redis / MQ
优点风险
极快进程挂则丢;需有界防 OOM
减少 RTT多实例间不共享,需 MQ 兜底

Disruptor(环形队列)用于超低延迟金融场景;一般业务 有界 BlockingQueue + 批量 flush 即可。

线程池隔离(舱壁)

用途
http-worker接口逻辑
mq-send发消息
db-io落库

慢 DB 占满 db-io 不影响接口接请求。


消息队列作为核心缓冲

峰值 10 万 QPS 写入
消费者 2 万 QPS 处理
→ MQ 积压上升,但**不打挂 DB**
→ 扩容消费者或容忍 lag
选型说明
Kafka高吞吐、日志型、可回溯
RocketMQ业务 MQ、定时消息
Redis Stream轻量、内存受限

监控:消费 lag、入队速率、拒绝率。


背压与过载保护

策略行为
排队超时等待 N ms 后 503
熔断下游错误率超阈值,直接失败
降级关排行榜、只记步数
负载丢弃非核心请求优先丢(需产品定义)

Little 定律队列长度 = 到达率 × 平均停留时间。只加机器不控到达率,队列仍会爆。


与排行榜结合

微信步数场景:

  1. 网关:每用户每秒 1 次上报限流
  2. 接入:校验后 只发 MQ,同步路径 < 10ms
  3. MQ:分区扩容消费
  4. 消费端:500ms 合并窗口 再写 Redis

排行榜与实时计数


相关