首页 / 知识库 / python服务端进阶 / 服务端高并发优化

04 - 异步化与削峰

缓存解决了「读」的压力。这一章解决另外两个问题:主流程被慢任务拖累突发流量打垮下游。核心工具就是你已经学过的消息队列

一句话先记住:异步让主流程「秒返回」,削峰让系统「扛得住高峰」,代价都是「允许任务晚一点完成」。

(消息队列的原理见《消息队列入门》系列,这里只讲它在高并发优化里扮演的角色。)


4.1 异步化:把非核心任务从主流程摘出去

问题:主流程被拖慢

以「用户下单」为例,同步串行做完所有事:

下单接口(同步):
 |── 写订单 ──|── 扣库存 ──|── 发短信 ──|── 加积分 ──|── 推荐更新 ──|
    0.05s        0.05s       1.5s        0.1s         0.8s
                          总计 ≈ 2.5s   ← 用户干等 2.5 秒

用户其实只关心「订单下成功了没」,发短信、加积分、更新推荐这些晚几秒完全无所谓

方案:非核心任务丢进队列

下单接口(异步):
 |── 写订单 ──|── 扣库存 ──|─丢消息─|  → 立刻返回(≈ 0.1s)
    0.05s        0.05s      0.001s
                              ╰──▶ 消息队列
                                     ├─▶ 短信服务(后台慢慢发)
                                     ├─▶ 积分服务
                                     └─▶ 推荐服务

用户等待从 2.5s 降到 0.1s,体验天差地别。

怎么判断能不能异步? 问一句:这件事,需要「现在立刻做完」才能给用户答复吗?

任务同步/异步原因
写订单主记录同步核心,必须成功
扣库存同步涉及一致性,要当场确认
发短信/邮件异步晚几秒无所谓
加积分、更新推荐异步后台算即可

4.2 削峰:用队列扛住突发流量

问题:峰值打垮下游

假设数据库每秒最多处理 200 个写请求。平时 100/s 岁月静好,秒杀一来瞬间 5000/s:

没有队列(直连):
  5000/s 洪峰


  ┌──────────┐
  │ 数据库     │ 每秒只能处理 200
  │ ⚡ 爆炸    │ ← 5000 瞬间压过来,直接崩
  └──────────┘

方案:队列当「蓄水池」

有队列(削峰填谷):
  5000/s 洪峰


  ┌────────────────────┐
  │   消息队列(蓄水池)   │  瞬时洪峰先排队
  │ [■■■■■■■■■■■■■■]      │  队列变长,但不崩
  └─────────┬──────────┘
            │ 消费者稳定按 200/s 取

       ┌──────────┐
       │ 数据库     │ 始终在能承受的速度内工作
       └──────────┘

洪峰被「削平」,摊到后面一段时间慢慢消化(填谷)。代价是高峰期任务会延迟,但系统不崩


4.3 异步化的两种实现方式

在 FastAPI 后端里,异步任务通常有两种做法:

方式适合场景特点
BackgroundTasks(FastAPI 内置)轻量、和请求同生命周期的小任务简单,但任务跑在同一进程,进程挂了任务就丢
消息队列 + 独立 Worker(如 Celery + RabbitMQ)重要的、耗时的、要保证不丢的任务独立进程消费,可重试、可持久化、可水平扩展

经验:无关紧要的小任务(记个日志)用 BackgroundTasks 就行;重要任务(发短信、支付回调处理)必须走消息队列,保证「丢不了、可重试」。


4.4 异步削峰的代价

  • 数据延迟:任务不是立刻完成的,用户可能「下单成功了但短信过一会儿才到」
  • 一致性变弱:主流程返回成功 ≠ 所有后续任务都成功,需要处理「消息丢失/重复/失败重试」
  • 系统更复杂:多了 Broker 和 Worker 要运维、要监控

什么时候用:任务「不需要实时完成」、或「流量有明显尖峰」、或「某服务不该拖垮主流程」时。反之,强一致、要即时结果的(如扣款结果),老老实实同步做。


本章小结

你要记住要点
异步化非核心任务丢队列,主流程秒返回
判断标准「需要现在立刻做完才能答复用户吗?」不需要就异步
削峰队列当蓄水池,洪峰先排队,消费者稳定消费
两种实现小任务用 BackgroundTasks,重要任务用消息队列 + Worker
代价数据延迟、弱一致、系统更复杂

下一章预告:无论同步异步,频繁「创建连接、创建线程」都是巨大浪费。池化技术教你「复用」。


上一章 ← 03 - 缓存:高并发第一利器 | 下一章 → 05 - 池化技术