消息队列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 的哈士奇最近也搞了个"狗队列"------叼个玩具要先在客厅转三圈才肯给我,还必须按"球→飞盘→绳结"的顺序,这就是它的"顺序消息"机制 😂

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


往期推荐:

相关推荐
wang09074 小时前
自己动手写一个spring之IOC_2
java·后端·spring
来杯@Java4 小时前
学生选课管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·maven·mybatis
不知名的老吴5 小时前
线程的生命周期之线程“插队“
java·开发语言·python
ANnianStriver5 小时前
PetLumina-02-后端开发与前后端联调
java·ai·sa-token
杨了个杨89826 小时前
Keepalived + Nginx + HAProxy 高可用架构部署实战案例
java·nginx·架构
马士兵教育8 小时前
Java还有前景吗?Java+AI大模型学习路线及项目?
java·人工智能·python·学习·机器学习
snow@li8 小时前
Java:理解 Gradle / 后端项目的管家 / 打包SpringBoot 应用 / 完成编译、下载依赖、运行测试、打包 JAR/WAR / 速查表
java
云烟成雨TD9 小时前
Spring AI 1.x 系列【57】动态工具发现:Tool Search Tool
java·人工智能·spring
zfoo-framework9 小时前
[修改代码使用]codex官方app中使用中转(不需要cc-switch) 1.config.toml 2.sk方式登录
java