01 - 为什么需要消息队列
先从一个真实的痛点说起
假设你用 FastAPI 做了一个”用户注册”接口。注册成功后,你还想做几件事:
- 往数据库写一条用户记录
- 发一封欢迎邮件
- 发一条短信验证码
- 给推荐系统推一条”新用户”事件
- 更新一下运营后台的统计数据
最直接的写法,是在这个接口里一件一件同步做完:
用户点"注册"
│
▼
┌─────────────────────────────────────────────┐
│ POST /register (FastAPI 接口函数里) │
│ │
│ 写数据库 (0.05s) │
│ → 发邮件 (2s,要连第三方邮件服务器) │
│ → 发短信 (1.5s,要连短信网关) │
│ → 推事件给推荐系统 (0.8s) │
│ → 更新统计 (0.3s) │
│ │
│ 全部做完 → 才返回"注册成功" │
└─────────────────────────────────────────────┘
│
▼
用户等了 4.6 秒,才看到"注册成功"
这里有三个越想越难受的问题:
问题一:用户被迫等待(慢)
用户其实只关心”我注册成功了没有”。可为了等邮件、短信这些跟他没关系的后续动作,他要多等好几秒。接口越挂越多的后续任务,用户等得越久。
问题二:任何一环挂了,整个注册就失败(脆)
如果邮件服务器那一刻抽风连不上,你的 发邮件 这一步抛异常,会怎么样?
整个注册接口报错,用户明明该注册成功,却看到”注册失败”。
一个”发欢迎邮件”这种无关紧要的动作,居然能拖垮核心的”注册”功能。这就是强耦合带来的脆弱。
问题三:流量一大就崩(扛不住高峰)
搞个促销活动,一瞬间涌进来 1 万人注册。每个请求都要同步发邮件、发短信……第三方短信网关每秒只能处理 200 条,你这边瞬间 1 万条压过去——短信网关被打爆,你的服务也跟着卡死。
换个思路:把”要做的事”先记下来,慢慢做
现实生活里我们早就这么干了。想想餐厅点餐:
- 你(顾客)把菜单交给服务员,服务员记一张小票贴到后厨的挂单栏,然后马上回来招呼下一桌。
- 你不用站在后厨盯着厨师炒菜,服务员也不用等菜做好才敢接待下一位。
- 厨师(们)按自己的节奏,从挂单栏一张张取小票来做。
- 高峰期挂单多,就多排一会队;但没有任何一桌会因为”厨房忙”被赶走。
这个”挂单栏”,就是消息队列。
顾客(生产者) 挂单栏(消息队列) 厨师(消费者)
┌──────────┐ ┌───────────────┐ ┌──────────┐
│ 下单: │──────▶│ 单1 单2 单3 … │──────▶│ 取单、做菜 │
│ "宫保鸡丁" │ 贴单 │ (先进先出排队) │ 取单 │ │
└──────────┘ └───────────────┘ └──────────┘
下完单就走 消息在这里排队 按自己节奏消费
不用等菜做好
用消息队列重构注册接口
回到刚才的注册例子。引入消息队列后,接口只做必须马上做完的核心动作,其余”通知类”任务,扔进队列就返回:
用户点"注册"
│
▼
┌───────────────────────────────┐
│ POST /register │
│ │
│ ① 写数据库 (0.05s) ← 核心,必须做│
│ ② 往队列丢一条"用户已注册"消息 │
│ (0.001s,丢完就不管了) │
│ │
│ 立刻返回"注册成功" │
└───────────────────────────────┘
│ 消息队列里躺着一条 "user_registered"
▼ │
用户 0.05 秒就看到"成功" ┌────────┴────────┐
▼ ▼ ▼
发邮件 发短信 推推荐/统计
(后台的消费者慢慢处理,各干各的)
对照一开始的三个问题,现在全解决了:
| 原来的问题 | 引入消息队列后 |
|---|---|
| 用户等 4.6 秒(慢) | 只等核心的 0.05 秒(异步) |
| 邮件挂了就注册失败(脆) | 邮件消费者自己重试,不影响注册(解耦) |
| 高峰把短信网关打爆(扛不住) | 消息在队列里排队,消费者按自己节奏慢慢消化(削峰) |
这三个关键词——异步、解耦、削峰——就是消息队列存在的全部意义,我们会在 第 03 章 展开讲。
一句话理解消息队列
消息队列(Message Queue)= 一个”中间人”,专门负责暂存和转发消息,让”发消息的人”和”处理消息的人”彼此不用直接打交道、也不用同时在线。
发消息的一方叫生产者,处理消息的一方叫消费者,中间那个存消息的服务叫 Broker(消息中间件)。这套模型,下一章我们仔细拆开看。
小结
- 痛点:把一堆后续任务同步串在一起做,会导致慢、脆、扛不住高峰。
- 消息队列的思路:像餐厅”挂单栏”一样,先把任务记下来排队,再由消费者按自己节奏处理。
- 它带来三大好处:异步(快)、解耦(稳)、削峰(扛得住)。
下一章 → 02 - 核心概念与工作模型