Kafka vs RocketMQ 深度技术选型对比

58 阅读27分钟

Kafka vs RocketMQ 深度技术选型对比

前言

在分布式系统架构中,消息中间件是实现系统解耦、异步处理、削峰填谷的核心组件。作为 Java 开发者,在技术选型时经常面临 Kafka 和 RocketMQ 的选择困境。本文将从技术架构、核心特性、性能优化、实际应用场景等多个维度深入对比两者,为技术选型提供决策依据。


一、技术架构深度对比

1.1 存储架构

Kafka 存储架构

核心设计思想: 顺序写磁盘 + PageCache + 零拷贝

Topic: order-topic (3 partitions)
partition-0/
  ├── 00000000000000000000.log         # Segment 文件(默认 1GB)
  ├── 00000000000000000000.index       # 稀疏索引(offset → 物理位置)
  ├── 00000000000000000000.timeindex   # 时间索引(timestamp → offset)
  ├── 00000000000005368709.log         # 下一个 Segment
  ├── 00000000000005368709.index
  └── 00000000000005368709.timeindex

日志分段机制:

  • 文件命名规则: 以当前 segment 的第一条消息 offset 命名
  • 分段优势:
    • 快速删除过期数据: 直接删除整个 Segment 文件,O(1) 时间复杂度
    • 加速查找: 通过二分查找定位到具体 Segment,再通过索引定位消息
    • 限制单文件大小: 避免单个文件过大影响性能

索引机制:

稀疏索引结构(.index):
┌────────────┬─────────────┐
│ Offset     │ Position    │  # 相对偏移量 → 物理字节位置
├────────────┼─────────────┤
│ 0          │ 0           │
│ 500        │ 20480       │  # 每隔 N 条消息建一个索引
│ 1000       │ 40960       │
└────────────┴─────────────┘

查找步骤:
1. 二分查找定位 Segment 文件
2. 在索引文件中二分查找最近的索引点
3. 从索引位置顺序扫描到目标消息

性能优化:

  • PageCache 机制: 利用操作系统页缓存,避免频繁磁盘 IO
  • 零拷贝技术: 使用 sendfile 系统调用,减少数据拷贝次数
  • 顺序写: 磁盘顺序写性能接近内存随机写

劣势:

  • 随机读性能较差: 需要从 Segment 文件顺序扫描
  • 不支持按 Key 查询: 必须知道 partition + offset
  • 历史消息查询效率低
RocketMQ 存储架构

核心设计思想: CommitLog + ConsumeQueue 分离架构

消息存储结构:
$HOME/store/
  ├── commitlog/              # 所有消息统一写入(顺序写)
  │   ├── 00000000000000000000
  │   └── 00000000001073741824  # 单文件默认 1GB
  │
  ├── consumequeue/           # 队列索引文件(按 Topic+QueueId 组织)
  │   ├── TopicTest/
  │   │   ├── 0/00000000000000000000
  │   │   ├── 1/00000000000000000000
  │   │   └── 2/00000000000000000000
  │
  └── index/                  # Hash 索引(支持按 Key/时间查询)
      └── 20250226010203456

存储流程:

1. Producer 发送消息
   ↓
2. 写入 CommitLog(顺序追加,所有 Topic 共享)
   ↓
3. 异步构建 ConsumeQueue(每个 Topic-Queue 独立索引)
   ├── 存储内容:CommitLog Offset + Size + TagHashCode
   └── 单条索引固定 20 字节
   ↓
4. 异步构建 IndexFile(可选,支持按 Key 查询)

ConsumeQueue 结构:

每条索引固定 20 字节:
┌──────────────┬──────┬──────────────┐
│ CommitLog    │ Size │ Tag HashCode │
│ Offset(8B)   │ (4B) │ (8B)         │
└──────────────┴──────┴──────────────┘

优势:
- 索引文件极小,全部加载到内存
- 消费时先读索引,再根据 offset 到 CommitLog 读消息
- 支持多个 Consumer 订阅同一 Topic 不同 Tag

IndexFile 索引机制:

支持按以下维度查询:
- 按 MessageKey 查询(精确匹配)
- 按时间范围查询
- 按 Topic 查询

索引结构(Hash 索引):
┌─────────────┐
│ Header      │  # 元数据(起止时间等)
├─────────────┤
│ Hash Slot   │  # Hash 槽(500万个槽)
├─────────────┤
│ Index Entry │  # 索引项(链表结构解决冲突)
└─────────────┘

性能优化:

  • 读写分离: 写走 CommitLog,读走 ConsumeQueue
  • 零拷贝: 使用 mmap + write 方式
  • 异步刷盘: 支持同步/异步刷盘策略
  • 索引加速: ConsumeQueue 加载到内存,消费速度快

优势:

  • 支持按 Key 查询消息
  • 支持按时间范围查询
  • 支持消息轨迹追踪
  • ConsumeQueue 小且快,消费性能高

劣势:

  • 存储结构复杂,维护成本高
  • 异步构建索引有延迟
  • 磁盘空间占用相对较大

1.2 集群架构

Kafka 集群架构
┌──────────────────────────────────────────┐
│ ZooKeeper / KRaft                        │
│  - Broker 元数据管理                      │
│  - Controller 选举                        │
│  - Topic 配置管理                         │
└────────────┬─────────────────────────────┘
             │
    ┌────────┴────────┬────────────┐
    ↓                 ↓            ↓
┌─────────┐      ┌─────────┐  ┌─────────┐
│ Broker-1│      │ Broker-2│  │ Broker-3│
│ (Leader)│      │(Replica)│  │(Replica)│
└─────────┘      └─────────┘  └─────────┘
    │                 │            │
    └─────────────────┴────────────┘
              Partition-0
            (Replication=3)

核心组件:

  • Controller: 集群控制器,负责 Partition Leader 选举
  • Broker: 消息存储节点
  • ZooKeeper/KRaft: 元数据管理(Kafka 3.x+ 支持 KRaft 去 ZK)

分区副本机制:

ISR(In-Sync Replicas)机制:
Leader:  Broker-1 [offset: 10000]
          同步复制
Replica: Broker-2 [offset: 9998]   ISR 中(滞后 < 10s)
Replica: Broker-3 [offset: 9500]  踢出 ISR(滞后 > 10s)

ISR 判断条件:
- replica.lag.time.max.ms (默认 10s)
- Follower 最后一次 Fetch 请求时间 < 10s

高可用保障:

  • Leader 选举: 从 ISR 中选举新 Leader
  • min.insync.replicas: 最少同步副本数(例如设置为 2)
  • acks=all: Producer 等待所有 ISR 副本确认

优势:

  • 架构简单,易于理解
  • 去 ZK 化(KRaft 模式)减少依赖
  • 副本机制成熟稳定

劣势:

  • Leader 选举依赖 ISR,极端情况可能无法选举
  • 不支持主从自动切换(需等待 ISR 恢复)
RocketMQ 集群架构
┌──────────────────────────────────────────┐
│ NameServer Cluster (无状态)              │
│  - 路由信息管理                           │
│  - Broker 心跳监听                        │
└────────────┬─────────────────────────────┘
             │ 心跳上报
    ┌────────┴────────┬────────────┐
    ↓                 ↓            ↓
┌─────────┐      ┌─────────┐  ┌─────────┐
│ Master-1│←────→│ Slave-1 │  │ Master-2│
│         │ 同步  │         │  │         │
└─────────┘      └─────────┘  └─────────┘
     │                │            │
     └────────────────┴────────────┘
          Producer/Consumer

核心组件:

  • NameServer: 轻量级注册中心(无状态,相互独立)
  • Broker Master: 处理读写请求
  • Broker Slave: 消息备份,可承担读请求

主从复制机制:

复制方式:
1. 同步复制(SYNC_MASTER)
   Master 写入后等待 Slave 同步完成再返回
   ✓ 高可靠
   ✗ 性能损失

2. 异步复制(ASYNC_MASTER)
   Master 写入后立即返回
   ✓ 高性能
   ✗ 可能丢消息

3. 半同步复制(推荐)
   重要消息同步,普通消息异步

高可用机制 (RocketMQ 5.x):

DLedger Controller 模式:
┌─────────────────────────────────────┐
│ DLedger Controller (基于 Raft)     │
│  - 自动 Master 选举                 │
│  - 元数据管理                       │
└─────────────┬───────────────────────┘
              │
    ┌─────────┴─────────┬──────────┐
    ↓                   ↓          ↓
┌────────┐        ┌────────┐  ┌────────┐
│ Broker │        │ Broker │  │ Broker │
│ Master │        │ Slave  │  │ Slave  │
└────────┘        └────────┘  └────────┘

Master 故障后:
1. Controller 检测到 Master 宕机
2. 从 Slave 中选举新 Master (基于 Raft 日志完整性)
3. 自动切换路由,秒级恢复

Slave Acting Master (SAM) 机制:

Slave 可临时接管 Master 角色:
1. Master 宕机
2. Slave 切换为 Acting Master(可读可写)
3. 原 Master 恢复后自动降级为 Slave

优势:

  • NameServer 无状态,易于扩展
  • 支持主从自动切换(5.x)
  • 消息可靠性高(同步复制 + 主从切换)

劣势:

  • 集群架构复杂
  • 需要配置主从关系
  • 4.x 版本主从切换需人工介入

1.3 数据复制架构

Kafka 数据复制
Replication 流程:
Producer
   ↓ acks=all
Leader (Broker-1)
   ↓ 写入本地 Log
   ↓ 等待 Follower Fetch
   ├──→ Follower-1 (Broker-2) [Fetch Request]
   │      ↓ 写入本地 Log
   │      ↓ 发送 ACK
   └──→ Follower-2 (Broker-3) [Fetch Request]
          ↓ 写入本地 Log
          ↓ 发送 ACK
   ↓ 收到所有 ISR ACK
返回 Producer 成功

HW (High Watermark) 机制:

Partition-0:
Leader:    [msg1][msg2][msg3][msg4][msg5]
           ─────────────────────↑ LEO (Log End Offset)
           ────────────────↑ HW (High Watermark)

Follower-1: [msg1][msg2][msg3][msg4]
Follower-2: [msg1][msg2][msg3][msg4]

HW = min(所有 ISR 副本的 LEO)
Consumer 只能读到 HW 之前的消息(已提交消息)

优势:

  • Follower 主动拉取,减轻 Leader 压力
  • HW 机制保证消息可见性一致

劣势:

  • 复制延迟取决于 Follower Fetch 频率
  • ISR 收缩可能导致可用性下降
RocketMQ 数据复制
同步复制流程:
Producer
   ↓
Master
   ↓ 写入 CommitLog
   ↓ 推送给 Slave
Slave
   ↓ 写入 CommitLog
   ↓ 返回 ACK
Master
   ↓ 返回 Producer 成功

CommitLog 复制机制:

Master CommitLog:
[msg1][msg2][msg3][msg4][msg5]
  ↓ 实时推送(HAService)
Slave CommitLog:
[msg1][msg2][msg3][msg4]

复制延迟监控:
slaveFallBehindMuch = Master Offset - Slave Offset

Quorum 写机制 (RocketMQ 5.x):

多副本写入策略:
┌──────────────┬──────────┬──────────┐
│ 写入策略      │ 副本数   │ 性能     │
├──────────────┼──────────┼──────────┤
│ 同步双写      │ ≥2       │ 低       │
│ 同步多写      │ ≥3       │ 最低     │
│ 自适应降级    │ 动态调整 │ 平衡     │
└──────────────┴──────────┴──────────┘

自适应降级逻辑:
1. 正常情况:同步写 3 副本
2. 某副本延迟 > 阈值:降级为同步写 2 副本
3. 延迟恢复:自动恢复 3 副本同步

优势:

  • 主动推送复制,延迟低
  • 支持灵活的复制策略
  • Quorum 机制提升可用性

劣势:

  • 同步复制性能损耗大
  • 主从关系固定,不如 Kafka 灵活

1.4 消费模型架构

Kafka 消费模型
Consumer Group 模型:
Topic: order-topic (4 partitions)
┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐
│ P-0  │  │ P-1  │  │ P-2  │  │ P-3  │
└───┬──┘  └───┬──┘  └───┬──┘  └───┬──┘
    │         │         │         │
    ↓         ↓         ↓         ↓
┌──────────────────────────────────────┐
│ Consumer Group: order-service        │
│  ├── Consumer-1 (消费 P-0, P-1)      │
│  └── Consumer-2 (消费 P-2, P-3)      │
└──────────────────────────────────────┘

核心原则:

  • 分区是最小并行单位: 一个分区只能被 Consumer Group 内一个 Consumer 消费
  • Consumer 数量 ≤ Partition 数量: 超过的 Consumer 空闲
  • Rebalance: Consumer 加入/退出时触发重新分配

Offset 管理:

Kafka 存储 Offset 位置:
__consumer_offsets (内部 Topic)
├── Key: (GroupId, Topic, Partition)
└── Value: Offset

提交方式:
1. 自动提交(enable.auto.commit=true-5s 自动提交一次
   - 风险:可能丢消息或重复消费

2. 手动提交(推荐)
   - commitSync(): 同步提交
   - commitAsync(): 异步提交

优势:

  • 简单高效,天然支持分区并行
  • Consumer 自主管理 Offset
  • 支持任意位置重置 Offset

劣势:

  • Consumer 数量受限于 Partition 数量
  • Rebalance 期间停止消费
  • 不支持按消息属性过滤
RocketMQ 消费模型
集群消费(Clustering):
Topic: order-topic (4 queues)
┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐
│ Q-0  │  │ Q-1  │  │ Q-2  │  │ Q-3  │
└───┬──┘  └───┬──┘  └───┬──┘  └───┬──┘
    │         │         │         │
    ↓         ↓         ↓         ↓
┌──────────────────────────────────────┐
│ Consumer Group: order-service        │
│  ├── Consumer-1 (消费 Q-0, Q-1)      │
│  └── Consumer-2 (消费 Q-2, Q-3)      │
└──────────────────────────────────────┘

广播消费(Broadcasting):
┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐
│ Q-0  │  │ Q-1  │  │ Q-2  │  │ Q-3  │
└───┬──┘  └───┬──┘  └───┬──┘  └───┬──┘
    │         │         │         │
    ├─────────┼─────────┼─────────┤
    ↓         ↓         ↓         ↓
Consumer-1  Consumer-2  ...(每个都消费全量)

Push vs Pull 模式:

Push 模式(实际是长轮询):
Consumer
   ↓ PullRequest (timeout=30s)
Broker
   ↓ 有消息立即返回,无消息挂起
   ↓ 30s 内有新消息主动推送
Consumer
   ↓ 消费消息
   ↓ 发送新的 PullRequest

优势:
- 实时性高
- 简化开发

POP 消费模式 (RocketMQ 5.x 新特性):

传统 Pull 模式问题:
- Consumer 需要维护队列分配关系
- Rebalance 逻辑复杂
- 客户端负担重

POP 模式:
Consumer
   ↓ Pop Request (无需指定队列)
Broker
   ↓ 自动分配消息
   ↓ 返回消息 + InvisibleTime
Consumer
   ↓ 消费成功后 ACK
   ↓ 消费失败或超时自动重新可见

优势:
- 无需 Rebalance
- 支持无限扩展 Consumer
- 类似 SQS/RabbitMQ 的消费体验

消息过滤:

支持多种过滤方式:
1. Tag 过滤(服务端过滤)
   consumer.subscribe("TopicTest", "TagA || TagB");

2. SQL92 过滤
   consumer.subscribe("TopicTest", 
       MessageSelector.bySql("age > 18 AND region = 'SH'"));

3. 类过滤模式(自定义 FilterServer

优势:

  • 支持广播消费
  • 支持消息过滤
  • POP 模式简化客户端逻辑
  • Consumer 数量不受队列限制

劣势:

  • Push 模式复杂度高
  • 消费进度管理需依赖 Broker

1.5 网络通信架构

Kafka 网络架构
Kafka 网络线程模型(Reactor 模型):
┌─────────────────────────────────────┐
│ Acceptor Thread (1个)               │
│  ↓ 接受连接                          │
│  ↓ 分配给 Processor                  │
└───────────┬─────────────────────────┘
            │
    ┌───────┴───────┬──────────┐
    ↓               ↓          ↓
┌────────┐    ┌────────┐  ┌────────┐
│Processor│    │Processor│ │Processor│  # 网络线程(num.network.threads=3)
│Thread-1│    │Thread-2│ │Thread-3│
└────┬───┘    └────┬───┘ └────┬───┘
     │             │          │
     └─────────────┴──────────┘
              ↓
     ┌────────────────────┐
     │ Request Queue      │  # 请求队列
     └────────┬───────────┘
              │
     ┌────────┴───────┬──────────┐
     ↓                ↓          ↓
┌─────────┐    ┌─────────┐  ┌─────────┐
│ Handler │    │ Handler │  │ Handler │  # IO 线程(num.io.threads=8)
│ Thread-1│    │ Thread-2│  │ Thread-3│
└─────────┘    └─────────┘  └─────────┘
     ↓                ↓          ↓
┌──────────────────────────────────────┐
│ Response Queue                       │
└──────────────────────────────────────┘

协议: 自定义二进制协议(高性能)

连接复用: Producer/Consumer 与 Broker 保持长连接

RocketMQ 网络架构
RocketMQ 网络模型(基于 Netty):
┌─────────────────────────────────────┐
│ Netty Boss Thread                   │
│  ↓ 接受连接                          │
└───────────┬─────────────────────────┘
            │
    ┌───────┴───────┬──────────┐
    ↓               ↓          ↓
┌────────┐    ┌────────┐  ┌────────┐
│ Worker │    │ Worker │  │ Worker │  # Netty IO 线程
│Thread-1│    │Thread-2│ │Thread-3│
└────┬───┘    └────┬───┘ └────┬───┘
     │             │          │
     └─────────────┴──────────┘
              ↓
     ┌────────────────────┐
     │ Business ThreadPool│  # 业务线程池(按请求类型分)
     ├────────────────────┤
     │ SendMessageThreadPool    (8 threads)  │
     │ PullMessageThreadPool    (16 threads) │
     │ QueryMessageThreadPool   (4 threads)  │
     │ AdminThreadPool          (4 threads)  │
     └────────────────────┘

协议:

  • Remoting 协议(默认,兼容性好)
  • gRPC 协议(RocketMQ 5.x,多语言支持)

优势:

  • Netty 高性能网络框架
  • 业务线程池隔离,避免相互影响
  • 支持多种协议

二、生产者/消费者端优化对比

2.1 生产者端优化

Kafka Producer 批量发送
// Kafka Producer 配置
Properties props = new Properties();

// 1. 批量发送配置
props.put("batch.size", 32768);           // 32KB,达到此大小立即发送
props.put("linger.ms", 10);               // 等待 10ms 凑批
props.put("buffer.memory", 33554432);     // 32MB 缓冲区
props.put("compression.type", "lz4");     // 压缩算法

// 2. 可靠性配置
props.put("acks", "all");                 // 等待所有 ISR 确认
props.put("retries", 3);                  // 重试 3 次
props.put("max.in.flight.requests.per.connection", 1); // 保证顺序

// 3. 性能配置
props.put("send.buffer.bytes", 131072);   // Socket 发送缓冲区 128KB
props.put("receive.buffer.bytes", 32768); // Socket 接收缓冲区 32KB

批量发送原理:

Producer 发送流程:
用户线程
   ↓ send(record)
RecordAccumulator (内存缓冲区)
   ├── Partition-0
   │   ├── Batch-1 (32KB) → 满了,触发发送
   │   └── Batch-2 (16KB) → 等待中
   ├── Partition-1
   │   └── Batch-1 (8KB)  → linger.ms 超时也发送
   │
   ↓ Sender 线程(后台 IO 线程)
   ↓ 压缩(lz4/snappy/gzip)
   ↓ 网络发送(批量)
Broker

发送时机:

  1. Batch 大小达到 batch.size
  2. linger.ms 时间到达
  3. 内存缓冲区满 (buffer.memory)
  4. 手动 flush()

性能提升:

  • 批量发送减少网络往返
  • 压缩提升网络传输效率
  • 顺序写磁盘提升 Broker 写入性能
RocketMQ Producer 批量发送
// RocketMQ Producer 配置
DefaultMQProducer producer = new DefaultMQProducer("producer_group");

// 1. 批量发送
List<Message> messages = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    Message msg = new Message("TopicTest", "TagA", 
        ("Hello RocketMQ " + i).getBytes());
    messages.add(msg);
}
// 批量发送(单次最大 4MB)
SendResult sendResult = producer.send(messages);

// 2. 异步发送
producer.send(msg, new SendCallback() {
    @Override
    public void onSuccess(SendResult sendResult) {
        System.out.println("发送成功");
    }
    
    @Override
    public void onException(Throwable e) {
        System.out.println("发送失败: " + e.getMessage());
    }
});

// 3. 单向发送(最高性能,不关心结果)
producer.sendOneway(msg);

RocketMQ 5.x 批量优化:

批量消息压缩优化:
1. 单条消息不压缩
2. 批量消息统一压缩(减少 CPU 开销)
3. 支持按大小自动分批(maxMessageSize=4MB)

批量发送限制:
- 同一批消息必须:
  ✓ 相同 Topic
  ✓ 不支持延迟消息
  ✓ 不支持事务消息

性能对比:

特性KafkaRocketMQ
自动批量✅ 自动凑批❌ 需手动批量
压缩支持✅ lz4/snappy/gzip✅ zip/lz4
批量大小限制batch.size 限制单次最大 4MB
异步发送✅ 支持✅ 支持

2.2 消费者端优化

Kafka Consumer 优化
// Kafka Consumer 配置
Properties props = new Properties();

// 1. 批量拉取配置
props.put("fetch.min.bytes", 1024);           // 最小拉取 1KB
props.put("fetch.max.wait.ms", 500);          // 最多等待 500ms
props.put("max.partition.fetch.bytes", 1048576); // 单分区最大拉取 1MB
props.put("max.poll.records", 500);           // 单次最多拉取 500 条

// 2. Consumer 并行度
props.put("num.consumer.fetchers", 2);        // 拉取线程数

// 3. Offset 提交
props.put("enable.auto.commit", false);       // 手动提交
props.put("auto.commit.interval.ms", 5000);   // 自动提交间隔

KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);

// 消费逻辑
while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
    
    // 批量消费
    for (ConsumerRecord<String, String> record : records) {
        process(record);
    }
    
    // 手动提交 Offset(处理完再提交,保证 At Least Once)
    consumer.commitSync();
}

优化策略:

1. 增加分区数提升并行度
   - Partition 数 = Consumer 数(最佳)
   - 过多 Partition 增加元数据开销

2. 批量拉取 + 批量处理
   - fetch.min.bytes:减少网络往返
   - max.poll.records:控制单批处理量

3. 异步 Offset 提交
   consumer.commitAsync(); // 不阻塞消费

4. 多线程消费
   - 单 Consumer 拉取,多线程处理
   - 注意线程安全和 Offset 管理
RocketMQ Consumer 优化
// RocketMQ Consumer 配置
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer_group");

// 1. 消费线程数配置
consumer.setConsumeThreadMin(20);           // 最小线程数
consumer.setConsumeThreadMax(64);           // 最大线程数

// 2. 批量消费配置
consumer.setConsumeMessageBatchMaxSize(32); // 单次最多消费 32 条
consumer.setPullBatchSize(32);              // 单次拉取 32 条

// 3. 消费并发数
consumer.setPullThresholdForQueue(1000);    // 队列最大消息数
consumer.setPullThresholdForTopic(2000);    // Topic 最大消息数

// 4. 消息消费超时
consumer.setConsumeTimeout(15);             // 15 分钟超时

// 注册监听器
consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(
            List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        
        // 批量消费(默认并发消费,无序)
        for (MessageExt msg : msgs) {
            process(msg);
        }
        
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

consumer.start();

并发消费 vs 顺序消费:

// 1. 并发消费(高吞吐)
consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(
            List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        // 多线程并发消费,不保证顺序
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

// 2. 顺序消费(保证顺序)
consumer.registerMessageListener(new MessageListenerOrderly() {
    @Override
    public ConsumeOrderlyStatus consumeMessage(
            List<MessageExt> msgs, ConsumeOrderlyContext context) {
        // 单线程顺序消费(按队列加锁)
        return ConsumeOrderlyStatus.SUCCESS;
    }
});

RocketMQ 5.x POP 消费优化:

// POP 消费模式(简化版)
DefaultLitePullConsumer consumer = new DefaultLitePullConsumer("consumer_group");
consumer.setAutoCommit(false);

while (true) {
    // 无需指定队列,Broker 自动分配
    List<MessageExt> messages = consumer.poll(Duration.ofSeconds(10));
    
    for (MessageExt msg : messages) {
        try {
            process(msg);
            // 消费成功,ACK
            consumer.commitSync();
        } catch (Exception e) {
            // 消费失败,不 ACK(消息自动重新可见)
            log.error("消费失败", e);
        }
    }
}

优势:
- 无需 Rebalance
- 支持无限扩展 Consumer
- 简化客户端逻辑

性能对比:

特性KafkaRocketMQ
批量拉取✅ 自动批量✅ 自动批量
消费线程池❌ 需自行实现✅ 内置线程池
顺序消费✅ 分区有序✅ 队列有序 + 全局有序
消息过滤❌ 不支持✅ Tag/SQL 过滤
消费重试❌ 需自行实现✅ 自动重试

三、核心特性与优劣势对比

3.1 消息顺序性

Kafka 顺序性保证

分区级别顺序:

Producer 保证顺序配置:
props.put("max.in.flight.requests.per.connection", 1); // 同时只有 1 个请求在途
props.put("enable.idempotence", true);                 // 开启幂等性

发送示例:
// 相同 Key 路由到同一 Partition
producer.send(new ProducerRecord<>("order-topic", orderId, message));

全局有序:

实现方式:
Topic 只设置 1 个 Partition

代价:
- 吞吐量受限(单线程写入)
- 无法并行消费
- 不推荐使用
RocketMQ 顺序性保证

队列级别顺序:

// 发送顺序消息(按 orderId 路由到同一队列)
producer.send(msg, new MessageQueueSelector() {
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        String orderId = (String) arg;
        int index = Math.abs(orderId.hashCode()) % mqs.size();
        return mqs.get(index);
    }
}, orderId);

全局顺序:

// 创建只有 1 个队列的 Topic
sh mqadmin updateTopic -t OrderTopic -n localhost:9876 -w 1 -r 1

// 消费端顺序消费
consumer.registerMessageListener(new MessageListenerOrderly() {
    @Override
    public ConsumeOrderlyStatus consumeMessage(
            List<MessageExt> msgs, ConsumeOrderlyContext context) {
        // 单线程顺序消费
        return ConsumeOrderlyStatus.SUCCESS;
    }
});

顺序消费原理:

RocketMQ 顺序消费锁机制:
1. Consumer 向 Broker 申请队列锁
2. 获得锁后才能消费该队列消息
3. 消费完一批后释放锁
4. 其他 Consumer 无法同时消费同一队列

优势:
- 保证严格顺序
- 支持队列级别并行

劣势:
- 某个消息消费失败会阻塞后续消息
- 消费性能下降

对比总结:

特性KafkaRocketMQ
分区/队列顺序✅ 支持✅ 支持
全局顺序✅ 支持(1 个分区)✅ 支持(1 个队列)
顺序保证机制分区写入顺序队列锁机制
消费失败处理需手动处理自动阻塞重试

3.2 消息可靠性

Kafka 可靠性保证

生产端可靠性:

// 1. ACK 配置
props.put("acks", "all"); // 等待所有 ISR 副本确认

acks=0: 不等待确认(最快,可能丢消息)
acks=1: 等待 Leader 确认(可能丢消息)
acks=all: 等待所有 ISR 确认(最可靠)

// 2. 重试配置
props.put("retries", 3);                     // 重试 3 次
props.put("retry.backoff.ms", 1000);         // 重试间隔 1s
props.put("delivery.timeout.ms", 120000);    // 总超时 120s

// 3. 幂等性
props.put("enable.idempotence", true);       // 防止重复消息

消费端可靠性:

// 手动提交 Offset(先处理再提交)
consumer.subscribe(Arrays.asList("topic"));

while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
    
    try {
        // 1. 处理消息
        for (ConsumerRecord<String, String> record : records) {
            processMessage(record);
        }
        
        // 2. 处理成功后再提交 Offset
        consumer.commitSync();
        
    } catch (Exception e) {
        log.error("消费失败", e);
        // 不提交 Offset,下次重新消费
    }
}

可靠性保障:

  • 幂等性: 通过 PID + Sequence Number 去重
  • 事务: 支持跨分区事务(Exactly Once)
  • 副本机制: ISR 保证数据不丢失
RocketMQ 可靠性保证

生产端可靠性:

// 1. 同步发送(等待 Broker 确认)
SendResult sendResult = producer.send(msg);
if (sendResult.getSendStatus() != SendStatus.SEND_OK) {
    // 处理发送失败
    log.error("发送失败: {}", sendResult);
}

// 2. 同步复制(Master + Slave 都写入成功)
// Broker 配置: brokerRole=SYNC_MASTER

// 3. 发送重试
producer.setRetryTimesWhenSendFailed(3);        // 同步发送失败重试 3 次
producer.setRetryTimesWhenSendAsyncFailed(3);   // 异步发送失败重试 3 次

消费端可靠性:

// 消费失败自动重试
consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(
            List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        try {
            processMessage(msgs);
            // 返回成功,Broker 删除消息
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        } catch (Exception e) {
            log.error("消费失败", e);
            // 返回稍后重试(默认最多重试 16 次)
            return ConsumeConcurrentlyStatus.RECONSUME_LATER;
        }
    }
});

// 消费重试机制:
// 第1次重试:10s 后
// 第2次重试:30s 后
// 第3次重试:1min 后
// ...
// 第16次重试:2h 后
// 超过 16 次进入死信队列(DLQ)

死信队列机制:

消息重试流程:
原始队列
   ↓ 消费失败
重试队列(%RETRY%ConsumerGroup)
   ↓ 重试 16 次仍失败
死信队列(%DLQ%ConsumerGroup)

处理死信消息:
1. 监控死信队列
2. 人工介入处理
3. 修复问题后重新投递

事务消息:

// RocketMQ 事务消息(本地事务 + 消息发送原子性)
TransactionMQProducer producer = new TransactionMQProducer("transaction_group");

producer.setTransactionListener(new TransactionListener() {
    @Override
    public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        try {
            // 1. 执行本地事务
            doLocalTransaction(arg);
            // 2. 提交事务
            return LocalTransactionState.COMMIT_MESSAGE;
        } catch (Exception e) {
            // 3. 回滚事务
            return LocalTransactionState.ROLLBACK_MESSAGE;
        }
    }
    
    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt msg) {
        // 4. 事务状态回查(Broker 定期回查未确定的事务)
        boolean success = checkTransactionStatus(msg);
        return success ? LocalTransactionState.COMMIT_MESSAGE 
                       : LocalTransactionState.ROLLBACK_MESSAGE;
    }
});

// 发送事务消息
producer.sendMessageInTransaction(msg, localTransactionArgs);

可靠性对比:

特性KafkaRocketMQ
生产端确认acks=all同步发送 + 同步复制
消费失败处理需自行实现自动重试 + 死信队列
事务支持✅ Exactly Once✅ 事务消息
消息轨迹❌ 不支持✅ 支持

3.3 延迟消息

Kafka 延迟消息

实现方式:

Kafka 原生不支持延迟消息,需自行实现:

方案 1:基于时间轮 + 内部 Topic
1. 发送延迟消息到 delay-topic
2. 消费者轮询 delay-topic
3. 检查消息时间戳,到期后转发到目标 Topic

方案 2:使用外部调度系统
- 延迟消息存储到 Redis/DB
- 定时任务扫描到期消息
- 发送到 Kafka

劣势:
- 需自行开发,复杂度高
- 性能和可靠性需自己保证
RocketMQ 延迟消息

固定延迟级别(4.x):

// 支持 18 个延迟级别
// 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

Message msg = new Message("TopicTest", "TagA", "Hello".getBytes());
// 延迟级别 3 = 10s
msg.setDelayTimeLevel(3);

producer.send(msg);

任意时间延迟(5.x 新特性):

// RocketMQ 5.x 支持任意时间延迟

Message msg = new Message("TopicTest", "TagA", "Hello".getBytes());

// 方式 1:延迟 30 分钟
msg.setDelayTimeSec(1800);

// 方式 2:指定投递时间
long deliverTime = System.currentTimeMillis() + 30 * 60 * 1000;
msg.setDeliverTimeMs(deliverTime);

producer.send(msg);

延迟消息原理:

RocketMQ 延迟消息实现:
1. 延迟消息先写入 SCHEDULE_TOPIC_XXXX
2. 按延迟时间组织到不同队列
3. 定时任务扫描到期消息
4. 转发到原始 Topic

优势:
- 原生支持,无需额外开发
- 性能高,可靠性强
- 5.x 支持任意时间延迟

对比总结:

特性KafkaRocketMQ
原生支持❌ 不支持✅ 支持
延迟精度-4.x: 18 个级别
5.x: 任意时间
实现复杂度高(需自行实现)低(开箱即用)

3.4 消息过滤

Kafka 消息过滤
Kafka 不支持服务端过滤,需客户端过滤:

consumer.subscribe(Arrays.asList("topic"));

while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
    
    for (ConsumerRecord<String, String> record : records) {
        // 客户端过滤
        if (matchFilter(record)) {
            processMessage(record);
        }
    }
}

劣势:
- 无效消息也需拉取,浪费带宽
- 客户端压力大
RocketMQ 消息过滤
// 1. Tag 过滤(最常用)
// 发送端
Message msg = new Message("TopicTest", "TagA", "Hello".getBytes());
producer.send(msg);

// 消费端(只消费 TagA 或 TagB)
consumer.subscribe("TopicTest", "TagA || TagB");

// 2. SQL92 过滤(需开启 enablePropertyFilter=true)
// 发送端
Message msg = new Message("TopicTest", "TagA", "Hello".getBytes());
msg.putUserProperty("age", "20");
msg.putUserProperty("region", "SH");
producer.send(msg);

// 消费端
consumer.subscribe("TopicTest", 
    MessageSelector.bySql("age > 18 AND region = 'SH'"));

// 3. 类过滤模式(自定义 Filter)
// 实现 MessageFilter 接口,部署到 FilterServer

过滤原理:

Tag 过滤:
- Tag 的 HashCode 存储在 ConsumeQueue
- 消费时先比对 HashCode(内存操作,快速)
- 匹配后再到 CommitLog 读取完整消息

SQL 过滤:
- 在 Broker 端执行 SQL 表达式
- 只返回匹配的消息给 Consumer

对比总结:

特性KafkaRocketMQ
服务端过滤❌ 不支持✅ 支持
过滤方式-Tag / SQL / 自定义
性能影响-低(索引加速)

3.5 消息堆积能力

Kafka 消息堆积
堆积能力:
- 基于磁盘存储,容量取决于磁盘大小
- 支持配置消息保留时间(log.retention.hours=168,默认 7 天)
- 支持配置消息保留大小(log.retention.bytes)

堆积性能:
- 顺序读磁盘 + PageCache,性能不会明显下降
- 即使堆积几百 GB 消息,消费性能仍然稳定

清理策略:
1. 基于时间清理(超过 7 天删除)
2. 基于大小清理(超过指定大小删除最老的 Segment)
3. Compaction(保留每个 Key 的最新值)
RocketMQ 消息堆积
堆积能力:
- 基于磁盘存储,容量取决于磁盘大小
- 支持配置消息保留时间(fileReservedTime=72,默认 3 天)

堆积性能:
- CommitLog 顺序写,性能稳定
- ConsumeQueue 索引文件小,全部加载到内存
- 堆积不影响消费性能

清理策略:
1. 定时清理(默认凌晨 4 点)
2. 磁盘空间不足时触发清理(磁盘使用率 > 75%)

对比总结:

特性KafkaRocketMQ
堆积能力✅ 百万级 TPS 堆积✅ 百万级 TPS 堆积
堆积对性能影响几乎无影响几乎无影响
默认保留时间7 天3 天

四、优劣势总结

4.1 Kafka 优势

  1. 超高吞吐量

    • 顺序写磁盘 + PageCache + 零拷贝
    • 批量发送 + 批量拉取
    • 适合日志收集、大数据场景
  2. 架构简单

    • 分区模型易于理解
    • 运维成本低
  3. 生态成熟

    • Kafka Streams(流处理)
    • Kafka Connect(数据集成)
    • 丰富的第三方工具
  4. 消息堆积能力强

    • 堆积不影响性能
    • 适合离线数据处理

4.2 Kafka 劣势

  1. 功能相对简单

    • 不支持延迟消息
    • 不支持消息过滤
    • 不支持消息轨迹
    • 消费失败需自行处理
  2. 消费扩展性受限

    • Consumer 数量 ≤ Partition 数量
    • 增加 Partition 需重新分配
  3. 运维复杂

    • 依赖 ZooKeeper(虽然 KRaft 已推出)
    • 集群扩容需要数据迁移

4.3 RocketMQ 优势

  1. 功能丰富

    • 延迟消息(任意时间延迟)
    • 消息过滤(Tag/SQL)
    • 事务消息
    • 消息轨迹
    • 死信队列
  2. 高可靠性

    • 同步复制 + 主从自动切换
    • 消费失败自动重试
    • 消息轨迹追踪
  3. 运维友好

    • 主从自动切换(5.x)
    • 丰富的监控指标
    • 控制台管理工具
  4. 灵活的消费模式

    • 集群消费 + 广播消费
    • POP 消费(5.x)
    • 顺序消费 + 并发消费

4.4 RocketMQ 劣势

  1. 吞吐量低于 Kafka

    • 存储结构复杂(CommitLog + ConsumeQueue)
    • 索引维护有开销
  2. 生态不如 Kafka 成熟

    • 第三方集成工具较少
    • 社区活跃度不如 Kafka
  3. 学习成本高

    • 概念较多(NameServer、Broker、Queue 等)
    • 配置参数复杂

五、技术选型实战案例

案例 1:电商订单系统

场景描述:

  • 订单创建后需要通知:库存系统、支付系统、物流系统、积分系统
  • 日订单量:100 万
  • 高峰 TPS:1 万
  • 要求:消息可靠、支持延迟消息(15 分钟未支付自动取消)

技术选型: RocketMQ

理由:

  1. 延迟消息: 原生支持延迟消息,实现"15 分钟未支付自动取消"逻辑简单
  2. 事务消息: 保证订单创建与消息发送的原子性
  3. 消息重试: 自动重试机制提升可靠性
  4. 消息轨迹: 方便排查订单消息流转问题

架构设计:

// 1. 订单创建 + 事务消息
TransactionMQProducer producer = new TransactionMQProducer("order_producer");

producer.setTransactionListener(new TransactionListener() {
    @Override
    public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        Order order = (Order) arg;
        try {
            // 创建订单(本地事务)
            orderService.createOrder(order);
            return LocalTransactionState.COMMIT_MESSAGE;
        } catch (Exception e) {
            return LocalTransactionState.ROLLBACK_MESSAGE;
        }
    }
    
    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt msg) {
        // 回查订单状态
        String orderId = msg.getKeys();
        Order order = orderService.getOrderById(orderId);
        return order != null ? LocalTransactionState.COMMIT_MESSAGE 
                             : LocalTransactionState.ROLLBACK_MESSAGE;
    }
});

// 发送事务消息
Message msg = new Message("order_topic", "order_created", order.toJson().getBytes());
msg.setKeys(order.getOrderId());
producer.sendMessageInTransaction(msg, order);

// 2. 延迟消息(15 分钟后取消订单)
Message delayMsg = new Message("order_topic", "order_cancel", order.getOrderId().getBytes());
delayMsg.setDelayTimeSec(15 * 60); // 延迟 15 分钟
producer.send(delayMsg);

案例 2:实时数据分析平台

场景描述:

  • 采集用户行为日志(点击、浏览、购买等)
  • 日志量:10 亿条/天
  • 高峰 TPS:10 万+
  • 要求:高吞吐、低延迟、支持实时计算

技术选型: Kafka

理由:

  1. 超高吞吐量: 顺序写 + PageCache + 零拷贝,轻松支持 10 万+ TPS
  2. 批量发送: 自动凑批,减少网络开销
  3. 生态集成: 与 Flink/Spark 无缝集成,支持实时计算
  4. 消息堆积: 支持离线数据回溯分析

架构设计:

// 1. 日志采集(批量发送)
KafkaProducer<String, String> producer = new KafkaProducer<>(props);

// 异步发送(高吞吐)
for (UserEvent event : events) {
    ProducerRecord<String, String> record = new ProducerRecord<>(
        "user_event_topic", event.getUserId(), event.toJson());
    
    producer.send(record, (metadata, exception) -> {
        if (exception != null) {
            log.error("发送失败", exception);
        }
    });
}

// 2. 实时计算(Flink 消费 Kafka)
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>(
    "user_event_topic",
    new SimpleStringSchema(),
    properties);

DataStream<UserEvent> stream = env.addSource(consumer)
    .map(json -> JSON.parseObject(json, UserEvent.class));

// 实时统计:5 分钟窗口内的点击量
stream.filter(event -> "click".equals(event.getEventType()))
    .keyBy(UserEvent::getUserId)
    .timeWindow(Time.minutes(5))
    .sum("clickCount")
    .print();

env.execute("Real-time Analytics");

案例 3:微服务系统异步解耦

场景描述:

  • 用户注册后需要:发送短信、发送邮件、初始化用户数据、发放优惠券
  • 日活:10 万
  • TPS:100-500
  • 要求:解耦、可靠、消息不丢失

技术选型: RocketMQ 或 Kafka 均可

对比分析:

维度RocketMQKafka
消息可靠性✅ 自动重试 + 死信队列⚠️ 需自行实现重试
开发成本✅ 低(功能丰富)⚠️ 中(需自行封装)
运维成本⚠️ 中(依赖 NameServer)✅ 低(生态成熟)
性能✅ 满足需求✅ 满足需求

推荐: RocketMQ(开箱即用,降低开发成本)

架构设计:

// 发送端
DefaultMQProducer producer = new DefaultMQProducer("user_producer");

// 用户注册成功后发送消息
Message msg = new Message("user_register_topic", "register", userId.getBytes());
SendResult result = producer.send(msg);

// 消费端(多个系统订阅同一 Topic)
// 1. 短信服务
DefaultMQPushConsumer smsConsumer = new DefaultMQPushConsumer("sms_consumer_group");
smsConsumer.subscribe("user_register_topic", "*");
smsConsumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
    sendSms(userId);
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});

// 2. 邮件服务
DefaultMQPushConsumer emailConsumer = new DefaultMQPushConsumer("email_consumer_group");
emailConsumer.subscribe("user_register_topic", "*");
emailConsumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
    sendEmail(userId);
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});

// 3. 优惠券服务
DefaultMQPushConsumer couponConsumer = new DefaultMQPushConsumer("coupon_consumer_group");
couponConsumer.subscribe("user_register_topic", "*");
couponConsumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
    grantCoupon(userId);
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});

案例 4:日志收集与监控

场景描述:

  • 收集微服务日志、应用日志、系统日志
  • 日志量:1 TB/天
  • 高峰 TPS:5 万+
  • 要求:高吞吐、低成本、支持日志回溯

技术选型: Kafka

理由:

  1. 超高吞吐量: 轻松支持 5 万+ TPS
  2. 消息堆积: 支持长时间保留(7-30 天)
  3. 生态集成: 与 ELK(Elasticsearch + Logstash + Kibana)无缝集成
  4. 成本低: 基于磁盘存储,成本远低于内存存储

架构设计:

日志收集链路:
应用日志 → Filebeat → Kafka → Logstash → Elasticsearch → Kibana

┌──────────┐
│ 微服务 A  │ → log file
└──────────┘       ↓
                Filebeat
                   ↓
┌──────────┐    Kafka
│ 微服务 B  │ → (log_topic)
└──────────┘       ↓
                Logstash
┌──────────┐       ↓
│ 微服务 C  │ → Elasticsearch
└──────────┘       ↓
                Kibana(查询分析)

六、选型决策树

┌─────────────────────────────────────┐
│ 你的业务场景是什么?                │
└──────────┬──────────────────────────┘
           │
           ↓
    是否需要超高吞吐量?
    (TPS > 10 万)
           │
     ┌─────┴─────┐
     ↓           ↓
    是          否
     │           │
     ↓           ↓
  选择 Kafka   是否需要延迟消息?
     │           │
     │      ┌────┴────┐
     │      ↓         ↓
     │     是        否
     │      │         │
     │      ↓         ↓
     │  RocketMQ  是否需要消息过滤?
     │      │         │
     │      │    ┌────┴────┐
     │      │    ↓         ↓
     │      │   是        否
     │      │    │         │
     │      │    ↓         ↓
     │      │ RocketMQ  是否需要消息轨迹?
     │      │    │         │
     │      │    │    ┌────┴────┐
     │      │    │    ↓         ↓
     │      │    │   是        否
     │      │    │    │         │
     │      │    │    ↓         ↓
     │      │    │ RocketMQ  两者均可
     │      │    │    │      (根据团队经验)
     └──────┴────┴────┴──────────┘

七、总结与建议

7.1 选型建议

选择 Kafka 的场景:

  1. 日志收集、大数据场景(高吞吐量优先)
  2. 实时数据分析(集成 Flink/Spark)
  3. 消息不需要复杂功能(延迟、过滤等)
  4. 团队有 Kafka 运维经验

选择 RocketMQ 的场景:

  1. 业务消息场景(订单、支付等)
  2. 需要延迟消息、事务消息
  3. 需要消息过滤、消息轨迹
  4. 对消息可靠性要求高

7.2 迁移建议

从 RabbitMQ 迁移到 Kafka/RocketMQ:

  • 高吞吐场景 → Kafka
  • 业务功能场景 → RocketMQ

从 Kafka 迁移到 RocketMQ:

  • 需要延迟消息、消息过滤等功能时考虑

从 RocketMQ 迁移到 Kafka:

  • 大数据场景,对生态集成要求高

7.3 最佳实践

Kafka 最佳实践
  1. 合理设置分区数

    • 分区数 = Consumer 数(最佳并行度)
    • 不宜过多(增加元数据开销)
  2. 使用批量发送

    • 配置合理的 batch.sizelinger.ms
    • 提升吞吐量
  3. 开启压缩

    • 推荐使用 lz4 压缩
    • 平衡压缩率和性能
  4. 手动提交 Offset

    • 先处理再提交,避免丢消息
    • 幂等处理,避免重复消费
RocketMQ 最佳实践
  1. 合理设置队列数

    • 队列数 = Consumer 数(最佳并行度)
    • 单 Broker 建议 4-8 个队列
  2. 使用同步发送 + 异步复制

    • 平衡性能和可靠性
    • 重要消息使用同步复制
  3. 配置消费线程池

    • 根据消息处理耗时调整线程数
    • IO 密集型:线程数 = CPU 核数 * 2
    • CPU 密集型:线程数 = CPU 核数 + 1
  4. 监控死信队列

    • 定期处理死信消息
    • 分析失败原因

7.4 性能对比表

维度KafkaRocketMQ
单机 TPS100 万+10 万+
消息延迟ms 级ms 级
消息堆积百万级百万级
高可用ISR 副本主从自动切换(5.x)
消息可靠性99.99%99.99%

7.5 成本对比

成本项KafkaRocketMQ
硬件成本低(顺序写,磁盘即可)低(顺序写,磁盘即可)
开发成本中(需封装功能)低(功能丰富)
运维成本低(生态成熟)中(运维工具较少)
学习成本低(概念简单)中(概念较多)

八、未来趋势

Kafka 发展方向

  1. KRaft 模式成熟:彻底去除 ZooKeeper 依赖
  2. Tiered Storage:冷热数据分层存储,降低成本
  3. 云原生:更好的容器化支持

RocketMQ 发展方向

  1. 存储计算分离:支持云存储(S3、OSS)
  2. Serverless:按量计费,降低使用门槛
  3. 多语言 SDK:完善 gRPC 多语言支持
  4. 流处理:增强 RocketMQ Streams 能力

参考资料

  1. Apache Kafka 官方文档
  2. Apache RocketMQ 官方文档
  3. RocketMQ 5.0 存储计算分离架构
  4. Kafka KRaft 架构
  5. 《Kafka 权威指南》
  6. 《RocketMQ 技术内幕》