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

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


往期推荐:

相关推荐
wno7042 小时前
Spring Security权限控制
java·python·spring
杨运交3 小时前
[071][验证码模块]基于Spring拦截器的验证码认证设计思想
java·后端·spring
Geek-Chow3 小时前
CountDownLatch in Java
java
SL_staff4 小时前
从RBAC到场景化授权:《无忧·企业文档》三级权限模型的技术实践解析
java·开源·产品
传奇开心果编程5 小时前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
SL_staff5 小时前
财务系统慎用低代码?从数据模型闭环看合规落地的技术实践
java·低代码·全栈
滕州市燕猫虎计算机科技工作室个体工商户5 小时前
IDEA:Command line is too long
java·ide·intellij-idea
步行cgn5 小时前
Spring p 命名空间注入详解
java·前端·spring
YatHinLay5 小时前
MyBatis 流式查询实战:ResultHandler 处理海量数据
java
天天被压力6 小时前
【跨市场数据实战 #08】可转债折价机会怎么筛:3个接口抓比价、列表和实时盘口
java·人工智能·python