6.0 KiB
第18天:SQS 与 SNS——消息队列和通知服务
今天你将学到什么
今天学习两个让系统"松耦合"的服务:SQS(消息队列)和 SNS(通知服务)。它们解决的核心问题是:让系统的各个部分不再紧密依赖,一个部分出问题不会拖垮整个系统。
为什么需要消息队列——用餐厅来理解
没有消息队列的世界(紧耦合)
想象一个餐厅,流程是这样的:
顾客点单 → 服务员站在厨房门口等 → 厨师做好菜 → 服务员端菜上桌 → 服务员回来接下一个顾客
问题:
- 服务员在等厨师做菜的时候什么都干不了(阻塞)
- 如果厨师突然肚子疼去了厕所,服务员和顾客都得干等(一个环节故障影响全部)
- 午餐高峰期 100 个人同时点单,厨房根本忙不过来(没有缓冲)
有消息队列的世界(松耦合)
改进后的流程:
顾客点单 → 服务员把订单贴在窗口(消息队列)→ 服务员立刻回去服务下一个顾客
厨师按自己的节奏从窗口取订单做菜 → 做好了放在出菜口 → 服务员来取
好处:
- 服务员不用等厨师(异步,不阻塞)
- 厨师去厕所了?订单还贴在窗口,回来继续做(容错)
- 高峰期订单堆在窗口,厨师按自己的速度做,不会崩溃(削峰)
- 可以加更多厨师来加快速度(水平扩展)
这就是消息队列的价值。
SQS(Simple Queue Service)
SQS 是 AWS 的消息队列服务——一个"订单窗口"。
工作流程
生产者(发送消息的人)→ SQS 队列 → 消费者(处理消息的人)
举个真实例子:电商下单流程
用户点击"提交订单"后,需要做很多事:
- 扣减库存
- 发送确认短信
- 生成物流单
- 更新用户积分
- 通知仓库备货
没有 SQS:所有步骤串行执行。用户要等所有步骤完成才看到"下单成功"。任何一步失败,整个订单失败。
有 SQS:
- 订单创建成功后立刻返回"下单成功"给用户(用户不用等)
- 同时把"有新订单"这个消息发到 SQS 队列
- 库存服务、短信服务、物流服务各自从队列取消息处理
- 某个服务暂时挂了?消息还在队列里,恢复后继续处理
SQS 的关键特性
消息保留:消息最多保留 14 天。如果 14 天内没人处理,才会被删除。
可见性超时:消费者取走一条消息后,这条消息对其他消费者"隐藏"一段时间。如果消费者处理成功就删除消息;如果处理失败(比如消费者崩溃了),超时后消息重新出现,可以被其他消费者重试。
死信队列:如果一条消息反复处理失败(比如重试了 5 次都失败),自动转移到"死信队列"。你可以人工检查这些"问题消息",避免它们阻塞正常处理。
SNS(Simple Notification Service)
SNS 是"发布/订阅"模式的通知服务——一条消息可以同时发给多个接收者。
SQS vs SNS 的区别
SQS = 点对点(一条消息只被一个消费者处理)
- 类比:快递柜。一个包裹只能被一个人取走。
SNS = 广播(一条消息发给所有订阅者)
- 类比:小区广播。一条通知所有住户都能听到。
SNS 的工作方式
发布者 → SNS 主题(Topic)→ 订阅者 A(邮箱)
→ 订阅者 B(短信)
→ 订阅者 C(SQS 队列)
→ 订阅者 D(Lambda 函数)
→ 订阅者 E(HTTP 接口)
举个例子:用户注册成功后
用户注册成功 → 发布"新用户注册"事件到 SNS
→ 邮件服务收到 → 发送欢迎邮件
→ 积分服务收到 → 赠送新人积分
→ 推荐服务收到 → 生成个性化推荐
→ 数据分析收到 → 记录注册统计
一个事件,多个服务各自处理自己关心的部分。互不影响。
经典组合:SNS + SQS(扇出模式)
这是 AWS 最推荐的异步架构模式:
订单服务发布"新订单"事件
↓
SNS 主题(广播给所有订阅者)
├── SQS 队列 A → 库存服务(扣减库存)
├── SQS 队列 B → 通知服务(发短信/邮件)
├── SQS 队列 C → 物流服务(生成运单)
└── SQS 队列 D → 积分服务(加积分)
为什么中间要加 SQS,不直接用 SNS 推给各服务?
因为 SQS 提供了"缓冲"和"重试":
- 某个服务暂时挂了 → 消息在 SQS 里等着,恢复后继续处理
- 某个服务处理慢 → 消息在 SQS 里排队,不会丢失
- 流量突然暴涨 → SQS 帮你削峰,各服务按自己的速度消费
同步 vs 异步:什么时候用哪种
| 场景 | 方式 | 原因 |
|---|---|---|
| 用户查询商品详情 | 同步 | 用户在等结果,必须立刻返回 |
| 用户下单扣库存 | 同步 | 必须确认库存够才能下单 |
| 下单后发确认短信 | 异步 | 短信晚几秒发不影响下单结果 |
| 下单后更新推荐 | 异步 | 推荐更新慢一点无所谓 |
| 上传图片后生成缩略图 | 异步 | 缩略图不需要立刻生成 |
判断标准:用户是否在等这个结果?如果是,同步。如果不是,异步。
今天的小测验
- 消息队列解决的核心问题是什么?用你自己的话解释。
- SQS 和 SNS 的区别是什么?各自适合什么场景?
- 什么是"死信队列"?它解决什么问题?
- 为什么说"SNS + SQS"是最佳组合?
延伸阅读
明天预告
明天是第二阶段的收尾:用一个完整的项目案例,把这 11 天学到的所有核心服务串联起来,看看它们在真实架构中是怎么配合工作的。