Appearance
第七部分:消息队列 MQ 高可用分布式、死信与最终一致性
第 1 章:RocketMQ & Kafka 分布式高可用物理架构
在高并发分布式系统中,消息队列 (MQ) 的高可用直接决定了系统的抗风险能力。
text
[ RocketMQ 高可用 ] ➔ NameServer 无状态集群 + Broker Master/Slave (SYNC_MASTER 双写 + SYNC_FLUSH 同步刷盘) + DLeger (Raft)
[ Kafka 高可用 ] ➔ Controller 控制器 + Topic 多 Partition + ISR (In-Sync Replicas) 动态副本 + acks=-1 (all)1.1 RocketMQ 分布式高可用与刷盘物理机制
text
[ NameServer 集群 ]
(无状态, 互不通信, 节点全量心跳)
│
┌──────────────────────┴──────────────────────┐
↓ ↓
[ Broker Group 1 ] [ Broker Group 2 ]
┌──────────────────────────┐ ┌──────────────────────────┐
│ Master 1 (SYNC_MASTER) │ ──(同步双写)──> │ Master 2 (SYNC_MASTER) │
│ Slave 1 (ASYNC_FLUSH) │ │ Slave 2 (ASYNC_FLUSH) │
└──────────────────────────┘ └──────────────────────────┘💬 RocketMQ 生产环境绝对零丢失配置
- 刷盘策略 (FlushDiskType):
ASYNC_FLUSH(异步刷盘,默认):PageCache 攒批后批量刷盘,性能极高,但断电可能丢少量数据;SYNC_FLUSH(同步刷盘):消息必须物理写入 OS 磁盘后才返回成功,保障数据不丢失。
- 复制策略 (BrokerRole):
SYNC_MASTER(同步双写):Master 收到消息后必须同步复制给至少 1 个 Slave,两者都写成功后才返回 Producer 成功;
- DLeger 自动选主 (基于 Raft 协议): 若开启 DLeger 组,当 Master 宕机后,多台 Broker 通过 DLeger 自动选举出新 Master,实现毫秒级无缝故障转移。
1.2 Kafka Partition 副本、ISR 机制与 ACK 三重物理含义
text
[ Topic: order_topic ]
└── [ Partition 0 ]
├── Leader 副本 (负责所有 Producer 写与 Consumer 读)
├── Follower 副本 1 (在 ISR 队列中,实时同步 ACK) ➔ [ ISR 列表: Leader, Follower 1 ]
└── Follower 副本 2 (同步延迟 > 10秒,被剔除出 ISR) ➔ [ OSR 列表: Follower 2 ]💬 Kafka acks 参数的三种物理含义与生产选型
Producer 配置 request.required.acks:
acks=0(极速无保障模式):- 机制:Producer 把消息发出去即代表成功,不等待 Leader 任何确认;
- 风险:网络抖动或 Leader 崩溃,消息直接丢失;适合日志收集 (
access_log);
acks=1(Leader 写入确认模式,默认):- 机制:Leader 副本成功写入物理日志后即返回成功;
- 风险:若 Leader 刚写完还没来得及同步给 Follower 就崩溃,仍会丢数据;
acks=-1或acks=all(最安全模式):- 机制:消息必须成功写入 ISR (In-Sync Replicas) 列表中的所有 Follower 副本 之后,才返回成功;
- 最佳实践:必须搭配
min.insync.replicas=2配置。即使 1 个 Leader 崩溃,ISR 中的 Follower 也会被 Controller 升为新 Leader,实现金融级绝对零丢失。
第 2 章:死信队列 (DLQ)、TTL+DLX 延迟队列与 100 万积压处理
2.1 死信队列 (DLQ) 三大产生条件与多语言搭建
text
[ Producer ] ➔ [ Normal Exchange / Queue ] ➔ (触发死信 3 条件) ➔ [ DLX (死信交换机) ] ➔ [ DLQ (死信队列) ] ➔ [ 人工干预 / 监控告警 ]💬 死信产生的 3 大物理条件
- 消息被 Consumer 显式拒绝:执行
basic.reject(requeue=false)或basic.nack(requeue=false); - 消息在 TTL (Time-To-Live) 生存时间到期后依然未被消费;
- 队列达到了最大物理长度限制 (
x-max-length),新到消息被挤出队列。
2.2 延迟队列中 UNPAID 状态机强校验机制
php
// 延迟消费 30 分钟未支付订单 - 消费端逻辑
public function handleDelayMessage(array $data) {
$orderId = $data['order_id'];
$order = Order::find($orderId);
// 核心物理强校验:绝不能直接关单!
if (!$order || $order->status !== 'UNPAID') {
// 订单已支付或已取消,直接安全丢弃消息
return true;
}
// 在本地事务中执行关单与退还库存
Db::transaction(function() use ($order) {
$order->status = 'CANCELLED';
$order->save();
Product::where('id', $order->product_id)->inc('stock', $order->num)->update();
});
}🔍 本章 6 重自审计报告
- 【知识审计】:已全量补充 RocketMQ 刷盘策略 (同步/异步刷盘)、SYNC_MASTER 同步双写、DLeger Raft 选主,以及 Kafka Partition 副本、ISR 动态队列、acks (0/1/-1) 参数物理含义与 UNPAID 状态机强校验!已适配移动端
::: info 💬自适应排版!