4. 消息队列中间件:Kafka 核心概念与选型实战

大家好,我是老张。今天咱们聊聊大屏监控系统里最关键的「数据管道」——消息队列。说实话,我见过不少团队,数据采集搞定了,存储也搭好了,结果中间的消息队列成了瓶颈。嗯,这节咱们就把它彻底讲透。

4.1 Kafka 核心概念:Topic、Partition、Consumer Group

先说说 Kafka 最基础的三个概念。你想想看,没有它们,Kafka 就是个空壳子。

4.1.1 Topic(主题)

Topic 说白了就是消息的分类标签。比如我们做大屏监控,会有「服务器CPU指标」、「网络流量数据」、「业务订单量」这些不同的数据流。每个数据流就是一个 Topic。

我个人习惯这样命名:monitor_cpu_usagemonitor_network_flow。清晰明了,运维同事一看就懂。

小提示:Topic 名称建议全小写,用下划线分隔。别用驼峰命名,我在项目中吃过这个亏——后来排查问题时大小写搞混了,浪费了半天时间。

4.1.2 Partition(分区)

Partition 是 Kafka 实现高吞吐的关键。一个 Topic 可以拆成多个 Partition,每个 Partition 是一个有序的、不可变的消息序列。

为什么会这样设计?因为单机处理能力有限。把数据分散到多个 Partition 上,就能并行读写。我做过一个项目,刚开始只设了 3 个 Partition,结果高峰期 CPU 指标堆积了 10 万条。后来改成 12 个 Partition,问题迎刃而解。

核心要点:
  • Partition 数量决定了并行度
  • 同一个 Partition 内的消息是有序的
  • 不同 Partition 之间不保证全局顺序
  • Partition 越多,吞吐越高,但管理成本也越大

4.1.3 Consumer Group(消费者组)

Consumer Group 是 Kafka 实现「广播」和「单播」的关键机制。同一个 Group 内的消费者,共同消费一个 Topic 的消息——每条消息只会被其中一个消费者处理。

举个例子:我们大屏监控系统有 3 台服务器做实时计算,它们属于同一个 Consumer Group。那么一条 CPU 指标数据,只会被其中一台服务器处理。这样既实现了负载均衡,又避免了重复计算。

我曾经遇到过一个坑:两个不同的业务模块(比如实时告警和历史存储)用了同一个 Consumer Group ID。结果告警模块处理了本该存储模块处理的数据,导致历史数据丢失。嗯,这个教训挺深刻的。

避坑指南:不同业务用途的消费者,一定要用不同的 Group ID。我曾经因为偷懒,把实时计算和历史归档的消费者放在同一个 Group 里,结果数据全乱了。

4.2 Kafka 高可用部署实战

Kafka 的高可用,说白了就是「挂了也不怕」。我建议至少部署 3 个 Broker 节点,配合副本机制来实现。

4.2.1 副本机制(Replication)

每个 Partition 可以设置多个副本。比如 replication.factor=3,意味着每个 Partition 有 3 个副本,分布在不同的 Broker 上。

副本分为 Leader 和 Follower。生产者只往 Leader 写,消费者也只从 Leader 读。Follower 负责同步数据。一旦 Leader 挂了,Controller 会从 Follower 中选举一个新的 Leader。

# 创建 Topic 时指定副本数
bin/kafka-topics.sh --create \
  --bootstrap-server broker1:9092,broker2:9092,broker3:9092 \
  --replication-factor 3 \
  --partitions 12 \
  --topic monitor_cpu_usage
我的建议:副本数一般设为 3 就够了。设太多浪费存储,设太少不安全。生产环境至少 3 个 Broker,副本数 3。

4.2.2 ISR 机制(In-Sync Replicas)

ISR 是 Kafka 保证数据一致性的关键。只有跟 Leader 保持同步的 Follower 才会被列入 ISR 列表。如果某个 Follower 落后太多,就会被踢出 ISR。

我记得有一次,某个 Broker 磁盘 IO 飙升,导致 Follower 同步延迟超过 30 秒。Kafka 自动把它踢出了 ISR,然后从其他 Follower 中重新选举了 Leader。整个过程业务无感知,这就是高可用的价值。

4.2.3 生产环境部署建议

配置项 推荐值 说明
Broker 数量 3 或 5 奇数个,方便选举
replication.factor 3 保证数据安全
min.insync.replicas 2 至少 2 个副本同步才算写入成功
acks all 生产者等待所有 ISR 确认
unclean.leader.election.enable false 不允许非 ISR 的副本成为 Leader
注意:unclean.leader.election.enable 一定要设为 false。虽然设为 true 能提高可用性,但会丢失数据。在大屏监控场景下,数据准确性比短暂的不可用更重要。

4.3 RabbitMQ 与 Kafka 选型对比

很多同学问我:「老张,到底该用 RabbitMQ 还是 Kafka?」我的回答是:看场景。

4.3.1 核心差异

对比维度 Kafka RabbitMQ
设计定位 分布式流处理平台 传统消息代理
吞吐量 百万级/秒 万级/秒
消息模型 拉模式(Pull) 推模式(Push)
消息持久化 磁盘顺序写,性能高 内存+磁盘,性能中等
消息顺序 Partition 内有序 队列内有序
路由能力 弱(基于 Topic) 强(Exchange + Routing Key)
延迟 毫秒级 微秒级

4.3.2 选型建议

我个人经验是这样的:

  • 大屏监控数据采集 → 选 Kafka:数据量大、吞吐要求高、需要持久化存储。我们每天处理 10 亿条指标数据,Kafka 稳如老狗。
  • 业务系统解耦 → 选 RabbitMQ:比如订单系统、支付系统之间的异步通知。需要灵活的路由策略,延迟要求高。
  • 日志收集 → 选 Kafka:配合 ELK 或 Flink,Kafka 是标准配置。
  • 任务调度 → 选 RabbitMQ:需要确认机制、死信队列等特性。
一句话总结:Kafka 适合「海量数据、高吞吐、顺序读写」的场景;RabbitMQ 适合「灵活路由、低延迟、业务解耦」的场景。别拿 Kafka 当普通消息队列用,也别拿 RabbitMQ 硬扛大数据量。

4.3.3 实战案例

我去年做过一个智慧城市的大屏项目。数据源包括:

  • 10 万台 IoT 设备,每秒上报 50 万条传感器数据
  • 200 个业务系统,每秒产生 5 万条业务日志
  • 实时告警系统,需要毫秒级响应

最终架构是这样的:

  • 传感器数据和业务日志 → Kafka(3 个 Broker,12 个 Partition,副本数 3)
  • 告警通知和任务调度 → RabbitMQ(集群模式,3 个节点)

运行一年,Kafka 端日均处理 40 亿条消息,RabbitMQ 端日均处理 200 万条消息。各司其职,相安无事。

我的经验:不要试图用一个消息队列解决所有问题。混合使用才是最佳实践。Kafka 做数据管道,RabbitMQ 做业务消息,各取所长。

好了,这节的内容就到这里。下一节咱们聊聊「数据采集 Agent 的设计与实现」,我会分享一个从零搭建采集 Agent 的实战案例,敬请期待。


公众号:蓝海资料掘金营,微信deep3321