vault backup: 2026-05-24 20:58:10

This commit is contained in:
hhs
2026-05-24 20:58:10 +08:00
parent 686c0a5bd5
commit fed75645c6
2 changed files with 115 additions and 4 deletions
@@ -1,6 +1,10 @@
---
tags:
- MQ
- 架构
- 异步
- 选型
- 流量削峰
create time: 2026-05-24 19:52
---
@@ -125,9 +129,37 @@ MQ 解决了分布式系统中的很多问题,但有些场景引入 MQ 反而
游戏服务器的实时状态同步、在线聊天等场景要求毫秒级响应。MQ 的存储转发机制会引入额外延迟,直接 WebSocket 或长连接更合适。
### 你需要 MQ 吗?——决策引导
在进入选型细节之前,先回答一个更根本的问题:**你的系统是否真的需要 MQ?**
很多团队在"技术潮流"的驱动下盲目引入 MQ,最后发现自己在用大炮打蚊子。下面这个流程图帮你快速判断:
```mermaid
graph TD
START["你有异步通信需求吗?"] -->|否| NO["不需要 MQ,直接调用即可"]
START -->|是| Q1{"需要解耦多个下游?"}
Q1 -->|是| YES["建议引入 MQ"]
Q1 -->|否| Q2{"有流量突增需要削峰?"}
Q2 -->|是| YES
Q2 -->|否| Q3{"有非核心链路可异步化?"}
Q3 -->|是| YES
Q3 -->|否| Q4{"需要消息持久化和重试?"}
Q4 -->|是| MAYBE["考虑 MQ 或轻量方案"]
Q4 -->|否| SIMPLE["考虑 goroutine 池或任务队列"]
style YES fill:#27AE60,color:#fff
style NO fill:#95A5A6,color:#fff
style MAYBE fill:#F39C12,color:#fff
style SIMPLE fill:#3498DB,color:#fff
```
> [!warning]
> 不要因为"别人在用"就引入 MQ。如果你的需求只是简单的后台任务,一个 goroutine 池 + channel 就能搞定,不需要动用分布式 Broker。
### 选型决策框架
选型时需要综合考虑以下维度,没有"最好"的 MQ,只有"最合适"的:
确认需要 MQ 后,选型时需要综合考虑以下维度。没有"最好"的 MQ,只有"最合适"的:
| 维度 | Kafka | RabbitMQ | RocketMQ | Pulsar |
|------|-------|----------|----------|--------|
@@ -138,6 +170,21 @@ MQ 解决了分布式系统中的很多问题,但有些场景引入 MQ 反而
| 生态 | 极丰富(Flink/Spark) | 成熟(插件体系) | 较丰富 | 成长中 |
| 典型场景 | 大数据管道、日志 | 企业应用、复杂路由 | 电商、金融 | 多租户、云原生 |
下面是基于核心需求的快速决策路径:
```mermaid
graph TD
START["确认需要 MQ"] --> Q1{"核心需求是什么?"}
Q1 -->|"大数据 / 日志管道"| Kafka["Kafka"]
Q1 -->|"灵活路由 / 企业集成"| RabbitMQ["RabbitMQ"]
Q1 -->|"事务消息 / 电商金融"| RocketMQ["RocketMQ"]
Q1 -->|"多租户 / 云原生"| Pulsar["Pulsar"]
Q1 -->|"极致轻量 / 低延迟"| NATS["NATS"]
```
> [!tip]
> 如果你拿不准,**RabbitMQ 是最稳妥的起步选择**——运维简单、文档完善、社区活跃。等业务规模增长后,再根据瓶颈点考虑迁移。更多维度的深度对比见 [[27-MQ-选型对比]]。
> [!question]
> 如果你的团队只有 3 个人,系统日均消息量 10 万条,你会选择哪个 MQ?为什么?
@@ -156,7 +203,35 @@ MQ 解决了分布式系统中的很多问题,但有些场景引入 MQ 反而
记住一个原则:**用户需要立即看到结果的操作,不要异步化。**
**忽略幂等设计**
这是引入 MQ 后最容易翻车的地方。网络抖动、消费者重启、Broker 重试都可能导致同一条消息被投递多次。如果消费者的处理逻辑不是幂等的,结果就是重复扣款、重复发货、重复积分。
```go
// 非幂等: 消息重投会导致重复扣款
func HandlePayment(msg Message) {
db.UpdateBalance(msg.UserID, -msg.Amount) // 每次执行都扣一次!
}
// 幂等: 利用消息 ID 做去重
func HandlePayment(msg Message) {
if db.Exists("processed:" + msg.ID) {
return // 已处理过,跳过
}
db.UpdateBalance(msg.UserID, -msg.Amount)
db.Set("processed:" + msg.ID, true)
}
```
> [!warning]
> 上 MQ 之前,先确保每个消费者都有幂等保障。幂等不是可选项,是必选项。详细设计见 [[14-MQ-消息幂等性]]。
## 关联笔记
- [[1-MQ-基础概念]]
- [[3-MQ-消息模型]]
- [[1-MQ-基础概念]] — MQ 是什么、核心术语、Pull/Push 模型
- [[3-MQ-消息模型]] — 队列与发布订阅模型的深入对比
- [[27-MQ-选型对比]] — 七大维度横向对比各主流 MQ
- [[14-MQ-消息幂等性]] — 幂等消费的设计方案
- [[12-MQ-消息确认与持久化]] — ACK 机制如何保证消息不丢
- [[16-MQ-死信队列与消息回溯]] — 消费失败后的兜底处理
- [[46-MQ-分布式事务实践]] — 事务消息在电商/金融场景的实战