消息队列解决什么
消息队列提供解耦、削峰与异步重试:生产者把消息交给队列后不必等待消费者,两者在时间上解耦;突发流量先落在队列里,消费者按自身速率处理。代价是系统复杂度上升——最终一致性、重复投递与顺序问题都需要业务侧显式处理。
投递语义
至多一次不重复但可能丢失,至少一次不丢但可能重复,精确一次只在受限范围内成立,通常依赖消费端幂等或事务实现。多数业务选择至少一次加幂等消费就够用,追求精确一次反而会引入不必要的复杂度与性能成本。
三种投递语义
| 语义 | 行为 | 代价 |
|---|---|---|
| 至多一次 | 不重复,可能丢失 | 可靠性最低 |
| 至少一次 | 不丢失,可能重复 | 需要消费端幂等 |
| 精确一次 | 不丢不重(限定范围) | 实现复杂,有性能成本 |
基本信息
| 顺序性 | 通常只在同一分区内保证,跨分区顺序需业务收敛 |
|---|---|
| 分区键 | 决定同一业务实体的消息是否落在同一分区 |
| 死信队列 | 承接反复失败的消息,便于人工排查 |
| 积压监控 | 消费延迟比队列长度更能反映真实问题 |
典型使用场景
- 订单异步处理:下单后异步通知库存与积分
- 日志与埋点收集:高吞吐写入,下游批量落库
- 削峰填谷:突发流量先入队,消费者按能力处理
- 跨系统数据同步:以事件驱动替代定时全量同步
- 失败任务重试:借助延迟队列与死信队列重试
选型看什么
先看投递语义与顺序保证,再看吞吐与延迟量级,最后看运维成本:是否需要独立集群、是否有成熟的监控与消息回溯工具、团队是否有人熟悉。轻量场景下用数据库表或对象存储加定时任务也能实现队列语义,引入中间件之前值得先确认业务量是否真的需要。
多数业务用至少一次加幂等消费即可;顺序性往往只在分区内成立,跨分区顺序需要业务侧收敛,不要假设队列提供全局有序。