消息队列Kafka/RocketMQ选型与高可用架构:从单体到100万TPS的演进

消息队列Kafka/RocketMQ选型与高可用架构:从单体到100万TPS的演进

大家好,我是迪哥。从 2019 年到 2026 年,我们的消息队列架构换了三波------从 ActiveMQ 到 RocketMQ,再到 Kafka 与 RocketMQ 并存。今天就聊聊,什么时候用 Kafka,什么时候用 RocketMQ,以及如何把它们搭得高可用。

选型对比:Kafka vs RocketMQ

维度 Kafka RocketMQ
吞吐量 极高(百万级) 高(十万级)
功能完整性 基础 丰富(延迟消息、事务消息、消息追踪)
运维复杂度 中等 简单
消息可靠性 高(不丢) 高(不丢/不重)
生态 完善(大数据生态) 一般
学习曲线 较陡 平缓

我们的最终策略:

  • Kafka:日志、事件流、大数据同步
  • RocketMQ:核心交易链路、订单、支付

RocketMQ 高可用架构部署

复制代码
                    ┌──────────────┐
                    │   Producer   │
                    └──────┬───────┘
                           │
            ┌──────────────┼──────────────┐
            │              │              │
      ┌─────▼─────┐  ┌────▼────┐  ┌────▼─────┐
      │ NameServer1│  │NameServer2│  │NameServer3 │
      └─────┬─────┘  └────┬────┘  └────┬─────┘
            │              │              │
      ┌─────▼──────────────▼──────────────▼─────┐
      │              Broker 集群                 │
      │  ┌──────────┐  ┌──────────┐  ┌─────────┐ │
      │  │Broker1-a │  │Broker2-a │  │Broker3-a│ │ (Master)
      │  └────┬─────┘  └────┬─────┘  └────┬────┘ │
      │  ┌────▼─────┐  ┌────▼─────┐ ┌────▼────┐ │
      │  │Broker1-s │  │Broker2-s │ │Broker3-s│ │ (Slave)
      │  └──────────┘  └──────────┘ └─────────┘ │
      └──────────────────────────────────────────┘
                  │
            ┌─────▼─────┐
            │ Consumer  │
            └───────────┘

Broker 配置示例

properties 复制代码
# broker.conf
brokerClusterName = order-cluster
brokerName = broker1
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER  # 异步复制,性能好
flushDiskType = ASYNC_FLUSH

# 从节点配置 broker-s.conf
brokerId = 1
brokerRole = SLAVE

Spring Boot 集成

java 复制代码
@RocketMQMessageListener(
    topic = "order-topic",
    consumerGroup = "order-consumer-group",
    selectorExpression = "*"
)
@Component
public class OrderConsumer implements RocketMQListener<Order> {
    @Override
    public void onMessage(Order order) {
        // 消费逻辑
        log.info("收到订单: {}", order.getOrderId());
    }
}

Kafka 高可用架构部署

复制代码
                    ┌──────────────┐
                    │   Producer   │
                    └──────┬───────┘
                           │
      ┌────────────────────┼────────────────────┐
      │                    │                    │
┌─────▼─────┐        ┌────▼─────┐        ┌────▼─────┐
│  ZooKeeper│        │Kafka Broker1│        │Kafka Broker2│
│  Ensemble │        │ (Controller)│        │ (Follower) │
└─────┬─────┘        └────┬──────┘        └────┬──────┘
      │                   │                    │
      └───────────────────┼────────────────────┘
                          │
                   ┌──────▼──────┐
                   │   Consumer  │
                   └─────────────┘

生产者配置

java 复制代码
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
          "kafka1:9092,kafka2:9092,kafka3:9092");
props.put(ProducerConfig.ACKS_CONFIG, "all");  // 等待所有 ISR 副本确认
props.put(ProducerConfig.RETRIES_CONFIG, 3);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
          StringSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
          StringSerializer.class.getName());
KafkaProducer<String, String> producer = new KafkaProducer<>(props);

ProducerRecord<String, String> record =
    new ProducerRecord<>("order-topic", "key", "value");
producer.send(record, (metadata, exception) -> {
    if (exception != null) {
        log.error("发送失败", exception);
    } else {
        log.info("发送成功 offset={}", metadata.offset());
    }
});

关键问题解决方案

1. 消息丢失问题

  • Kafkaacks=all + min.insync.replicas=2 + 幂等生产者
  • RocketMQ:同步刷盘 + 同步复制 + 事务消息

2. 消息重复问题

业务层保证幂等:

java 复制代码
@Service
public class OrderService {
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Transactional
    public void createOrder(Order order) {
        // 1. 先存数据库(自带幂等性)
        orderMapper.insert(order);
        // 2. 再发消息
        rocketMQTemplate.syncSend("order-topic", order);
    }
}

3. 消息积压问题

  • ✅ 增加 Consumer 数量(不超过分区数)
  • ✅ 临时降级非核心业务
  • ✅ 消息堆积报警
yaml 复制代码
# Prometheus 报警规则
groups:
- name: kafka_alerts
  rules:
  - alert: ConsumerLagHigh
    expr: kafka_consumergroup_lag > 10000
    for: 5m
    labels:
      severity: warning

4. 延迟消息

RocketMQ 原生支持:

java 复制代码
Message msg = new Message(
    "order-topic",
    ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET)
);
// 3 秒后投递
msg.setDelayTimeLevel(3);
rocketMQTemplate.send(msg);

最佳实践清单

场景 推荐方案
日志/大数据/高吞吐 Kafka
核心交易/订单/支付 RocketMQ
消息可靠性优先 acks=all / SYNC_MASTER
延迟敏感 linger.ms=0 / 同步刷盘
顺序消息 单分区 + 单 Consumer

最终效果

指标 优化前 优化后
峰值 TPS 5 万 100 万+
消息可靠性 99.9% 99.999%
故障恢复时间 1 小时 < 1 分钟

说到消息队列,我家那只叫 Docker 的哈士奇最近也搞了个"狗队列"------叼个玩具要先在客厅转三圈才肯给我,还必须按"球→飞盘→绳结"的顺序,这就是它的"顺序消息"机制 😂

我是迪哥,我们下期再见!


往期推荐:

相关推荐
晨曦中的暮雨1 小时前
4.15腾讯 CSIG云服务产线 一面
java·开发语言
2301_781571421 小时前
Golang格式化输出占位符都有什么_Golang fmt占位符教程【通俗】
jvm·数据库·python
fake_ss1981 小时前
AI时代学习全栈项目开发的新范式
java·人工智能·学习·架构·个人开发·学习方法
茉莉玫瑰花茶2 小时前
工作流的常见模式 [ 1 ]
java·服务器·前端
未若君雅裁2 小时前
Spring AOP、日志切面与声明式事务原理
java·后端·spring
No8g攻城狮3 小时前
【人大金仓】wsl2+ubuntu22.04安装人大金仓数据库V9
java·数据库·spring boot·非关系型数据库
xiaoerbuyu12333 小时前
开源Java 邮箱 基于SpringBoot+Vue前后端分离的电子邮件
java·开发语言
C+++Python3 小时前
C++ 进阶学习完整指南
java·c++·学习