跳转至

如何保证消息队列高可用?

一、Broker 高可用

1. 主从复制

  • 同步复制:主写成功等至少一个从写成功才返回。数据不丢,但延迟高。
  • 异步复制:主写成功立即返回,从异步同步。性能高,但主挂可能丢少量消息。
  • 半同步:至少一个从收到即返回,平衡。

2. 自动故障转移

  • RocketMQ:Dledger / Controller 模式,主挂自动选从。
  • Kafka:KRaft(去 ZooKeeper)模式,Controller 选举。
  • RabbitMQ:镜像队列 / Quorum Queue。

二、生产端高可用

1. 发送重试

producer.send(msg, new SendCallback() {
    public void onSuccess(SendResult r) {}
    public void onException(Throwable e) {
        // 重试
    }
});

2. 同步刷盘 / 异步刷盘

  • 同步刷盘:消息写磁盘才返回,不丢但慢。
  • 异步刷盘:写 Page Cache 即返回,快但宕机丢数据。

金融场景用同步刷盘,普通业务用异步。

三、消费端高可用

1. 集群消费 + Rebalance

一个消费组多个实例,Queue 自动分配到不同实例。某实例挂了,Queue 重新分配给其他实例。

2. 手动 ACK

处理完业务再 ACK;异常不 ACK,MQ 会重投。

3. 死信队列

多次消费失败的消息进 DLQ,避免一直重试阻塞。

四、消息不丢的三段保障

  1. 生产端:发送成功确认 + 失败重试。
  2. Broker:持久化 + 主从复制。
  3. 消费端:处理完再 ACK,业务幂等。

五、消息不重复

MQ 保证 At least once,所以可能重复。消费端必须幂等:

  • 唯一业务 ID + Redis 去重。
  • 数据库唯一索引。
  • 状态机:已处理状态直接跳过。

六、监控与运维

  • 堆积监控:consumer_lag
  • 失败率、重试率。
  • Broker 磁盘、网络。
  • 定期巡检死信队列。

高频追问

  • Kafka 高可用靠 Partition 多副本 + ISR(In-Sync Replicas)。
  • RocketMQ 主从同步,主写从读,主挂不自动切(DLedger 后支持自动选主)。