高可用与核心概念

一、为什么用 MQ?--- 三大核心价值

|----------------------|-----------------------|------------------|
| 价值 | 说明 | 举例 |
| 解耦(Decoupling) | 生产者和消费者不直接调用,通过 MQ 中转 | 订单系统不需要知道物流系统的接口 |
| 异步(Async) | 非核心流程异步化,快速返回响应 | 注册后异步发邮件、送优惠券 |
| 削峰(Peak Shaving) | 高峰请求暂存 MQ,消费者按自己速度处理 | 秒杀场景,避免瞬间压垮后端 |

复制代码
没有 MQ:                           有 MQ:
用户 → 订单 → 库存 → 短信 → 返回    用户 → 订单 → MQ → 返回(快!)
              ↘ 物流                            ↓
                ↘ 积分                    库存 → 短信 → 物流 → 积分
       (每一步都等,timeout 风险)        (异步消费,不怕超时)

二、消息可靠性的全链路保障:如何不丢消息?

2.1 消息丢失的三个阶段

复制代码
Producer ──①──→ Broker ──②──→ Consumer
   ↑              ↑              ↑
 生产阶段       存储阶段        消费阶段

|----------|-----------------|---------------------------|
| 阶段 | 丢失原因 | RocketMQ 解决方案 |
| 生产阶段 | 网络问题,发送失败 | ① 同步发送 + 重试 ② 事务消息(半消息机制) |
| 存储阶段 | Broker 宕机/磁盘故障 | ① 同步刷盘 ② 主从同步复制 |
| 消费阶段 | 消费者拿到消息但没处理完就挂了 | ① 处理完再 ACK ② 重试机制 + 死信兜底 |

2.2 各阶段具体配置

生产阶段:

复制代码
// 同步发送 + 失败重试
producer.setRetryTimesWhenSendFailed(3);  // 重试 3 次
SendResult result = producer.send(message);  // 同步等结果

存储阶段:

复制代码
# Broker 配置:同步刷盘 + 同步复制 = 金融级可靠性
flushDiskType=SYNC_FLUSH
brokerRole=SYNC_MASTER

消费阶段:

复制代码
// 一定在业务处理成功后再返回 CONSUME_SUCCESS
// 不要先返回再异步处理!
@Override
public ConsumeConcurrentlyStatus consumeMessage(...) {
    try {
        doBusiness(msg);
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;  // 成功才 ACK
    } catch (Exception e) {
        return ConsumeConcurrentlyStatus.RECONSUME_LATER;   // 失败触发重试
    }
}

2.3 可靠性 vs 吞吐量的权衡

复制代码
可靠性: 同步刷盘 + 同步复制 + 同步发送 → 一条不丢,但慢
吞吐量: 异步刷盘 + 异步复制 + 异步发送 → 极快,但可能丢

实战经验:一般业务用异步刷盘 + 异步复制足够了,不然性能根本扛不住。金融支付类才用全同步。


三、消息堆积(积压)--- 如何处理?

3.1 积压原因

  • 消费者处理慢(SQL 慢、下游接口超时)
  • 消费者宕机或数量不够
  • 瞬时流量洪峰

3.2 解决方案

|------------------|------------------------------------------|------------------------|
| 方案 | 操作 | 适用场景 |
| 紧急扩容消费者 | 增加 Consumer 实例数 | Consumer 数量 < Queue 数 |
| 临时新 Topic 转发 | 原 Topic 的消息快速转到新 Topic,增加新 Consumer 并行处理 | 大量积压需要快速消化 |
| 消费逻辑优化 | 批量消费、异步处理、减少 DB 调用 | 性能瓶颈在消费逻辑 |
| 增加 Queue 数量 | 修改 Topic 的 Queue 数(不能减少) | Queue 太少导致并行度不够 |

3.3 积压处理的标准流程

复制代码
① 确认积压量级(控制台 / 监控)
     ↓
② 紧急修复消费逻辑(如果代码有 bug)
     ↓
③ 增加 Consumer 实例(最好到 Queue 数量上限)
     ↓
④ 如果还不行 → 创建新 Topic,将原 Topic 积压消息转发到新 Topic
     新起 N 台 Consumer 处理新 Topic
     ↓
⑤ 积压消化完 → 恢复原架构

四、RocketMQ 部署模式

|--------------------------|------------|------------------------------------|
| 模式 | 结构 | 特点 |
| 单 Master | 1 个 Master | 开发测试用,挂了就没了 |
| 多 Master | 多个 Master | 无 Slave,Master 挂则该 Master 上的消息不可消费 |
| 多 Master 多 Slave(异步) | 2M-2S,异步复制 | 生产常用,性能好,少量丢数据 |
| 多 Master 多 Slave(同步) | 2M-2S,同步复制 | 金融级,数据最安全 |

生产环境推荐:2M-2S 异步复制。


五、ConsumerGroup 消费进度(Offset)管理

|----------|-------------|---------|
| 消费模式 | Offset 存储位置 | 说明 |
| 集群模式 | Broker 端 | 重启不会丢进度 |
| 广播模式 | Consumer 本地 | 重启会丢失进度 |

Offset 存储结构:

复制代码
~/store/config/consumerOffset.json
{
    "Topic@ConsumerGroup": {
        "0": 1024,   // Queue 0 消费到 offset 1024
        "1": 2048    // Queue 1 消费到 offset 2048
    }
}

六、RocketMQ vs Kafka vs RabbitMQ

|----------|---------------------|------------|-------------|
| 对比维度 | RocketMQ | Kafka | RabbitMQ |
| 开发语言 | Java | Scala/Java | Erlang |
| 吞吐量 | ★★★★★(十万级) | ★★★★★(十万级) | ★★★(万级) |
| 延时 | 毫秒级 | 毫秒级 | 微秒级 |
| 消息顺序 | 天然支持 | 分区内有序 | 不保证 |
| 事务消息 | 原生支持 | 需要外挂 | 不支持 |
| 延时消息 | 原生支持(18级) | 不原生支持 | 插件支持 |
| 消息过滤 | Tag + SQL(Broker 端) | 消费端过滤 | Routing Key |
| 可用性 | 主从 + 自动切换 | 分布式 + ISR | 镜像队列 |
| 适用场景 | 电商、金融、大规模分布式 | 大数据、日志、流处理 | 微服务、低延时 |

选型建议

复制代码
大数据 / 日志 / 流计算  →  Kafka(生态最强)
高可靠 / 事务 / 金融支付 →  RocketMQ(阿里系最优)
低延时 / 路由复杂      →  RabbitMQ(管理界面友好)

七、RocketMQ 5.x 新特性(面试加分项)

|--------------------|-----------------------------|
| 特性 | 说明 |
| Pop 消费模式 | 解决传统 Push 模式下的消费堆积和负载不均问题 |
| 轻量级 SDK (gRPC) | 多语言支持更强(Go/Python/C++/Rust) |
| Proxy 无状态化 | 计算与存储分离,弹性伸缩 |
| Controller 模式 | 替代 ZooKeeper 做主从切换 |


八、完整的消息生命周期

复制代码
┌─────────────────────────────────────────────────────┐
│               NameServer 集群(路由中心)              │
│                   ns1  ns2  ns3                     │
└────┬──────────────────┬──────────────────┬─────────┘
     │                  │                  │
     ▼                  ▼                  ▼
┌─────────┐     ┌──────────────┐     ┌──────────┐
│Producer │────→│ Broker 集群   │────→│ Consumer │
│         │     │ Master-Slave │     │          │
│ group1  │     │  CommitLog   │     │ group1   │
│         │     │ ConsumeQueue │     │          │
└─────────┘     └──────────────┘     └──────────┘
     │                  │                  │
     └── 重试/容错 ─────┴── 重试/死信 ────┘

消息流转:
创建 → 路由选择 → 发送 → 存储(CommitLog) → 索引(ConsumeQueue)
→ 投递 → 消费 → ACK → 清理(过期/删除)
                 ↓ 失败
            重试队列 → (16次后) → 死信队列 → 3天后清除
相关推荐
小羊没烦恼!2 小时前
深入浅出SQL Server中的死锁
java·开发语言·前端·数据库·后端·spring·c#
白露与泡影2 小时前
Java 面试八股文及答案整理 | 后端面试高频题(2026)
java·开发语言·面试
\光辉岁月/2 小时前
6.数组工具类
java·数组·数组工具类
hai_android3 小时前
Android 设备锁定:Kiosk Mode 实战
android·java·android jetpack
张伯毅3 小时前
External Shuffle Service(spark3_shuffle):原理、配置与排障
java·开发语言·spark·yarn
high一马平川3 小时前
# SystemUI Dagger2 精读 · 第 2 章 @Inject:1200 处构造注入,和 1 处例外
android·java·kotlin
小陈从不会敲代码3 小时前
JavaEE面试复习(多线程-初阶)
java·面试·java-ee
周厉3 小时前
酒店PMS系统设计:房型房价管理与动态价格优先级实现(Java/MySQL)
java·数据库·pms酒店系统
一碗白开水一3 小时前
Day 5 · 弹性 | 微观
java·前端·数据库