ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Kafka KRaft模式架构解析:从ZooKeeper依赖到自管理元数据集群部署

Kafka KRaft模式架构解析:从ZooKeeper依赖到自管理元数据集群部署 记得我刚接触 Kafka 那会儿还是 2.x 时代搭个测试集群得先伺候好 ZooKeeper三台 ZK 节点一旦脑裂整个集群的元数据就跟着抽风。后来社区憋了好几年的大招——KRaft 模式终于在 3.3 版本转正把 ZooKeeper 彻底踢出了 Kafka 的依赖列表。这两年我在生产环境里把 Kafka 集群从 ZK 模式迁移到了 KRaft 模式踩了不少坑也摸清了这套新架构的门道。这篇东西不是官方文档的翻译是我基于 KRaft 模式架构做的梳理和实操总结适合正在做技术选型、准备搭新集群、或者刚接手 Kafka 运维的工程师。我会把 KRaft 的架构原理、3 节点集群的部署全过程、以及消息延迟和顺序性这些高频问题的排查思路都过一遍全程只讲实际用得上的东西。1. 为什么要放弃 ZooKeeperKRaft 模式解决的核心问题1.1 ZooKeeper 时代的架构痛点如果你经历过 ZK 模式的 Kafka一定对下面这些场面不陌生。Kafka 的 broker 节点把分区元数据、消费者组位移、Controller 选举结果全部交给 ZooKeeper 保管但 Kafka 和 ZooKeeper 是两个独立系统它们之间的数据一致性靠的是 ZK 的 ZAB 协议而 Kafka 自己对元数据变更的处理又有一套缓存逻辑这就导致一个很尴尬的局面ZK 里的数据和 Kafka 内存里的视图经常出现短暂的错位。最典型的问题是 Controller 切换时间不可控。Controller 负责分区 leader 的选举和元数据下发一旦它挂了需要等 ZK 会话超时默认 6 秒新的 Controller 才能被选举出来。这 6 秒里整个集群的 partition leader 都无法变更生产环境里这就是一段明显的服务抖动。我见过不少团队为了缩短这个时间把 session.timeout 调得很小结果 ZK 网络稍微抖一下broker 就被误判为失联触发一轮无意义的 rebalance搞得消费端全在报错。另一个痛点是运维复杂度。ZK 集群本身要 3 台起步版本还得跟 Kafka 匹配升级顺序要先升 ZK 再升 Kafka一个环节错了就起不来。而且 ZK 的 watcher 机制在 broker 数量多了之后会很敏感单个 ZK 节点压力大了整个集群的稳定性跟着下降。1.2 KRaft 模式的架构核心与设计思路KRaft 模式说白了就是把 ZooKeeper 干的活全部收编回 Kafka 自己的进程里。它在 Kafka 内部引入了独立的 Controller 角色专门负责管理元数据和集群状态Controller 之间通过 Raft 共识算法也就是 KRaft 里的 Quorum来同步决策和选举。这带来的第一个好处是组件数量减半。以前至少要 3 台 ZK N 台 broker现在只需要 N 台运行 KRaft 模式的 broker其中一部分节点同时承担 Controller 角色。生产环境里常见的做法是给刚搭建的集群分配 3 个节点每个节点都启用 controller 角色组成一个 3 节点的 Quorum。第二个好处是 Controller 切换速度大幅提升。以前 Controller 故障恢复要等 ZK 会话超时现在 Controller 节点之间走的是 KRaft 自带的 Raft 心跳机制故障切换能控制在秒级甚至毫秒级而且整个切换过程对客户端基本透明。还有一个容易被忽略的设计变化KRaft 模式下broker 不再需要连接外部 ZK而是从内部元数据日志读取元数据。这意味着集群的数据链路里少了一跳外部依赖网络分区、ZK 集群抖动这类故障场景直接消失了。同时 Controller 可以把元数据周期性地写入一个内部主题 __cluster_metadata这就为后续的元数据高可用和快速恢复打好了基础。1.3 元数据管理的变化从 ZK 节点到元数据日志在 ZK 模式下Kafka 的元数据以 znode 形式散落在 ZK 的目录树里比如 /brokers/ids、/brokers/topics、/controller 等等。ZK 负责这些数据的强一致Kafka 侧用 ZkClient 监听变化并刷新自己的缓存。这个机制本身很成熟但它的问题是元数据更新路径长、链条多而且 ZK 的写入性能和 Kafka 内部 topic 的写入性能不在一个量级。KRaft 模式下元数据被统一封装进一个特殊的内部主题 __cluster_metadata。这个主题不参与普通的业务读写专门记录集群的元数据变更事件如创建 topic、新增 broker、分区 leader 切换、配置变更等。每个 KRaft 节点都会从元数据日志里读取并维护自己的元数据缓存Controller 作为日志的 leader 负责接收和发布这些变更。这里面有一个关键的转变Kafka 对元数据的管理从外部系统依赖变成了自身日志机制的延伸。好处是元数据的写入速率不再受 ZK 性能限制后续如果要横向扩展 brokerController 的下发效率也更高了。而且元数据日志同样是紧凑型日志可以像普通 topic 一样做定期清理避免无限增长。2. KRaft 模式的核心组件与关键机制2.1 Controller 角色与 Quorum 机制KRaft 模式下的节点角色分为两种Controller 和 Broker。一个节点可以同时承担两种角色也可以只承担一种。在部署时通过 process.roles 参数配置比如 configuration/controller 表示只当 Controllerbroker 表示只当 brokercontrollerbroker 表示混合。Controller 的主要职责是监听 broker 的心跳、处理集群元数据变更、触发分区 leader 选举、下发元数据变更到所有 broker。多个 Controller 节点组成一个 Raft 群组也就是 Quorum它们之间通过 controller.quorum.voters 参数互相发现。Quorum 内部选举产生一个 Active Controller其他 Controller 作为备用节点随时准备接管。这里的 Raft 算法逻辑和常见的 etcd、Consul 实现类似节点之间通过投票选出 leaderleader 接收写请求并把日志复制到大多数节点然后再响应客户端请求。Kafka 的做法是把这个 Raft 组内嵌在自己的 Controller 进程里不依赖外部组件。所以在 KRaft 模式下Controller 的可用性由 Raft 的多数派保证3 节点 Quorum 可以容忍 1 台故障5 节点可以容忍 2 台故障。实际部署时需要权衡一点Controller 节点并不是越多越好。因为每个 Controller 都参与 Raft 日志复制节点越多写元数据需要到达的副本数就越多元数据变更的延迟会更高。一般中小规模集群 3 个 Controller 节点足矣如果对可用性要求更高才用 5 个。2.2 元数据 Topic__cluster_metadata 的运作方式KRaft 模式里最核心的内部存储就是 __cluster_metadata 这个元数据主题。它跟普通用户主题最大的区别在于普通主题的数据是业务数据根据配置的副本因子存储在多个 broker 上而 __cluster_metadata 只存储元数据事件它由 Controller 负责写入并且所有运行中的 broker 节点都会消费它来同步自己的元数据缓存。这个设计有点像一个“中心化发布、全员订阅”的配置中心。Controller 收到创建 topic 请求后会生成一条记录写入元数据日志日志条目在 Quorum 里复制成功后Controller 才向客户端返回成功。之后其他 broker 通过拉取元数据日志感知到这个变更更新自己的本地缓存。整个流程没有外部依赖而且因为日志复制是顺序追加的元数据变更的顺序天然被严格保证了。有一个我在实践中踩过的坑在 KRaft 模式下直接删除某些内部状态文件可能会导致节点启动异常。比如元数据日志目录 metadata 下如果有损坏的 segment节点启动时可能会无限重试。这时候不要想着去手工删除日志文件正确的做法是确保集群里至少有一个节点的元数据日志是完整的用那个节点的副本做恢复。2.3 数据链路不变分区与副本机制的正常运转KRaft 模式改变的是元数据管理链路但 Kafka 数据链路本身——producer 到 leader partition、leader 到 follower 的日志复制、consumer 从分区拉数据——完全没有变化。也就是说你不需要担心 KRaft 模式会改变消息的生产消费语义分区数、副本数、ISRIn-Sync Replicas这些概念照旧适用。这里要特别注意一个生产环境里容易踩的问题在 KRaft 模式下broker 的副本机制和 leader 选举极大程度依赖 Controller 及时响应。如果 Controller 节点负载过高或者 Controller 与某个 broker 的网络出现延迟分区 leader 的切换效率会受到影响。所以我通常建议把 Controller 和 Broker 的 CPU、内存资源做一定程度的隔离至少在容器化部署里要给 Controller 进程预留足够的资源。另外一个值得提醒的点是磁盘规划。KRaft 模式下每个 broker 节点除了要存储业务数据的分区日志还要存储元数据日志。如果两者共用同一块磁盘元数据日志的写入频率虽然不高但一旦磁盘空间耗尽Controller 会无法提交新的元数据变更导致集群进入只读状态。所以我一般建议要么用两块独立磁盘分别存储数据日志和元数据日志要么在监控告警里对磁盘使用率设置一个比较保守的阈值比如 80% 就告警。3. 3 节点集群部署实操完整配置与验证过程3.1 环境准备与版本选择KRaft 模式从 Kafka 3.3 开始正式可以用于生产环境到 3.6 之后已经相当成熟我现在生产环境用的是 3.7 版本。如果你要新部署集群我的建议是直接用 3.6 及以上版本不需要再从 ZK 模式过渡。硬件上3 节点集群的每台机器至少要有 4 核 CPU 和 8GB 内存磁盘用 SSD 最好机械盘在元数据日志同步和高吞吐场景下会成为瓶颈。操作系统用 Linux 系CentOS 7 或者 Ubuntu 20.04 以上都可以。这里再强调一下网络规划。3 个节点之间的网络延迟要尽量低因为 KRaft 的 Controller 选举和数据复制都在这个内网里完成。不建议跨可用区部署 Controller 节点如果非要跨区至少保证 2 个节点在同一区域。3.2 配置文件逐项解析节点配置文件是 KRaft 模式部署里最需要仔细核对的部分。以节点 1 为例核心配置如下process.rolesbroker,controller node.id1 controller.quorum.voters1kafka1:9093,2kafka2:9093,3kafka3:9093 listenersPLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 advertised.listenersPLAINTEXT://kafka1:9092 controller.listener.namesCONTROLLER inter.broker.listener.namePLAINTEXT log.dirs/data/kafka-logs metadata.log.dir/data/kafka-metadata num.partitions3 default.replication.factor3 min.insync.replicas2逐项解释几个容易被忽略的配置项process.roles声明节点的角色。3 节点集群里我让每台都同时跑 broker 和 controller节省节点同时保证 Controller 数量为 3。controller.quorum.voters三个 Controller 节点的地址列表格式是 nodeidhost:port 的逗号分隔列表。这里配置必须所有节点一致。controller.listener.names指定 Controller 之间通信使用的 listener 名称这里定义的是 CONTROLLER。advertised.listeners对外广播的地址客户端和 broker 之间连接靠这个配置。这里注意一定要写成其他节点能访问到的地址不能写 127.0.0.1。metadata.log.dirKRaft 模式新增的配置指定元数据日志的存储位置。我特意独立成单独的目录避免和数据日志混在一起。min.insync.replicasISR 最小副本数设为 2这样在 broker 故障时还能保证写入可用性。节点 2 和节点 3 的配置除了 node.id 和 advertised.listeners 之外其他保持一致。节点 2 的 node.id2advertised.listeners 对应 kafka2 的地址节点 3 同理。3.3 格式化与集群启动流程在 KRaft 模式下启动之前需要先做一步格式化操作但这一步现在比 ZK 时代简单很多。关键是要用 kafka-storage.sh 给元数据日志目录生成一个集群 ID 并完成格式化。命令如下# 先为集群生成一个唯一的 ID KAFKA_CLUSTER_ID$(bin/kafka-storage.sh random-uuid) # 在每个节点上执行格式化 bin/kafka-storage.sh format -t $KAFKA_CLUSTER_ID -c config/server.properties注意format 命令只在第一次初始化时执行。如果节点已经运行过再次 format 会清空元数据日志等于重新初始化这个操作在生产环境里是毁灭性的。我在测试环境里就吃过这个亏误以为重新 format 是更新配置的必要步骤结果整个集群的元数据被清空所有 topic 都没了。格式化完成后依次启动三个节点的 Kafka 进程bin/kafka-server-start.sh -daemon config/server.properties启动顺序其实没有严格限制但建议先从 Controller 节点开始这样后续 broker 加入时能更快完成元数据同步。启动后确认进程正常jps # 应该能看到 Kafka 进程然后检查节点的 Controller 和 broker 状态。可以用 kafka-metadata-quorum 命令验证 Quorum 是否正常bin/kafka-metadata-quorum.sh --bootstrap-server kafka1:9092 describe --status正常输出的内容里应该能看到当前活跃的 Controller 节点 ID以及 Quorum 的在线节点数。如果显示多数派节点在线说明元数据层是健康的。3.4 常用验证命令与可视化工具接入集群起来之后先用最简单的命令验证基础功能# 创建测试 topic bin/kafka-topics.sh --bootstrap-server kafka1:9092 --create --topic test-kraft --partitions 3 --replication-factor 3 # 查看 topic 详情 bin/kafka-topics.sh --bootstrap-server kafka1:9092 --describe --topic test-kraft # 启动一个简单的生产消费验证 bin/kafka-console-producer.sh --bootstrap-server kafka1:9092 --topic test-kraft bin/kafka-console-consumer.sh --bootstrap-server kafka1:9092 --topic test-kraft --from-beginning日常监控运维可视化工具方面我常用的有两类一类是 Kafka 原生的命令行加 JMX 监控比如 Prometheus 配 kafka_exporter另一类是 AKHQ 或者 Kafka UI 这类 Web 控制台。AKHQ 的好处是既能看 topic 和消费组信息还能直接操作部分管理任务比如查看 Kafka Connect 任务的状态。看过不少人在 AKHQ 里找 connector 任务找不到位置这里提一句入口在 AKHQ 的界面左侧菜单栏里有一个 Connect 的入口点进去才能看到所有已部署的 connector 和 task这些信息不是放在 Kafka topics 页面的。还有AKHQ 本身不读取业务 topic 的数据它是通过 Kafka AdminClient 获取的集群元数据来展示内容所以只要集群元数据正常AKHQ 就能正常展示。4. 消息延迟高与消费顺序性的排查思路4.1 消息延迟高的定位方法与常见原因消息延迟高是 Kafka 生产环境里最高频的问题之一我想先给出一个排查的基本思路延迟可能出在链路的不同环节不要一上来就怀疑 broker。第一个环节是生产者延迟。客户端发送消息时如果 producer 端 linger.ms 设置过大或者 batch.size 配置不合理会导致消息在客户端堆积看起来就是消息延迟高。此外 acks 配置如果是 all加上 min.insync.replicas 过大写入一条消息需要等待多个副本确认在只有 2 个 ISR 副本的情况下会有额外的往返开销。第二个环节是 broker 写入延迟。这里主要看磁盘性能。如果 Kafka 数据日志所在磁盘的 IO 等待时间高比如机械盘或共享存储出现抖动消息落盘的时间就会被拉长。可以用 iostat 查看磁盘的 %util 和 svctm如果 %util 持续超过 80% 就要引起注意了。第三个环节是消费端延迟。消费端处理不过来最常见的表现是 lag 持续上涨而 broker 本身没有异常。这种情况下应该优先看消费端单条消息的处理耗时、消费线程数、以及是否有阻塞调用比如同步调外部接口。还有一个容易被忽略的问题消费端如果频繁触发 rebalance比如 session.timeout.ms 设置过短或者 max.poll.interval.ms 设置不合理整个消费组会不停进出 rebalance 状态导致消费进度停滞。对于这些延迟问题中文社区里很多人喜欢一上来就改一堆 broker 参数但我的经验是先把链路数据对齐确认延迟到底卡在哪一段再针对性地调整配置。4.2 消费端多线程如何保证消息顺序性消息顺序性是另一个高频面试和生产问题。Kafka 的分区机制保证了同一个分区内的消息是有序的但你一旦在消费端引入多线程这个顺序性很容易被打破。先明确一个基本点Kafka 能保证的顺序范围是分区级别即同一个 key 的消息会被路由到同一个分区且该分区内的写入顺序和消费顺序一致。所以如果你需要严格顺序生产端要确保消息 key 的设定能让相关消息落到同一个分区。消费端多线程的场景下我常用的方案是“单分区单线程”加“负载均衡线程池”的混合模式。具体来说如果你的业务必须严格保证同一 key 或同一类消息的顺序那就在消费端不启用并发用单个线程处理同一个分区。如果你的业务场景能让不同 key 的消息独立处理就可以按 key 做哈希分发到多个工作线程。实操里我构建过这样一个模型主消费线程拉取消息后不立即处理而是将消息按 key 哈希到多个队列中每个队列绑定一个工作线程。这样同一个 key 的消息始终被同一个线程处理不同 key 可以并行性能和处理顺序都能兼顾。需要注意的一点是 rebalance 期间的处理顺序问题。消费线程正在处理消息时消费组发生 rebalance分区被分配给另一个消费者这时候已经拉取但尚未处理完的消息如果直接丢弃会导致消息丢失。比较稳妥的处理方式是在 rebalance 监听器里先暂停处理、完成位移提交、再释放分区。这个细节在做多线程消费的时候尤其重要我在多个项目里都见过因为 rebalance 和线程池没有协调好导致的消息丢失。如果只是做简单的多线程消费而不关心顺序直接用 ConcurrentKafkaConsumer 的思路要注意线程安全问题。Kafka 的 KafkaConsumer 本身不是线程安全的不要试图在多个线程里共享同一个 consumer 实例。正确做法是每个消费线程创建独立的 consumer 实例订阅不同的分区集合。4.3 AdminClient 与监控可视化集群管理的日常操作AdminClient 是 Kafka 提供的管理接口它可以在 Java 代码里动态创建 topic、查看集群状态、修改配置不需要登录服务器执行命令行。运维脚本化之后很多日常操作效率提升非常明显。比如我要批量给一批 topic 调整 retention 时间可以用 AdminClient 的 alterConfigs 方法去修改 log.retention.ms。或者我想确认某个消费组的 lag 分布可以用 listConsumerGroupOffsets 配合 describeConsumerGroups 来算。代码里一个注意点是AdminClient 的实例创建后要及时关闭否则会持续占用连接资源。还有在 KRaft 模式下AdminClient 的操作路径和 ZK 模式基本一致但部分操作比如 fetch metadata会走新的 Controller 链路遇到超时的时候可以对比是不是 Controller 节点负载问题。可视化监控方面生产环境我推荐 Prometheus Grafana 的组合。kafka_exporter 能采集每个 topic 的分区 lag结合 AlertManager 配置 lag 超过阈值自动告警。这套方案的优势是全开源、接入成本低而且可以自定义告警规则。AKHQ 和 Kafka UI 这类工具适合日常人工查看它们的优点是界面直观能快速看到 topic、消费组、broker 状态。但我不建议把它们作为唯一监控手段因为它们不会主动告警很多问题等到你想起来点开界面看一眼的时候已经影响业务了。5. 常见问题排查与集群运维避坑指南5.1 InvalidReceiveException 等网络层报错解析在 Kafka 运维中org.apache.kafka.common.network.InvalidReceiveException 是一个比较典型的网络层报错。这个异常通常出现在客户端和 broker 的 TCP 连接建立后broker 收到了不符合协议格式的数据包于是主动断开连接。这个报错最常见的触发原因是客户端和服务端的 Kafka 协议版本不兼容。比如使用较新版本的客户端连接较旧版本的 broker或者反过来双方在 ApiVersions 协商阶段就出现了信息不匹配。另外如果客户端发送了超过 socket.request.max.bytes 配置大小的请求比如生产端设置的 max.request.size 超过了 broker 允许的上限broker 也会拒绝这个请求并抛出 InvalidReceiveException。排查这类报错的思路是先看客户端和服务端的版本日志确认两边版本兼容然后检查客户端的 max.request.size 和 broker 的 socket.request.max.bytes 是否匹配最后用抓包或者 broker 侧的网络日志确认是否有异常数据包进入。这里有一个从实战中得来的经验如果在容器化环境里部署 Kafka客户端频繁报 InvalidReceiveException很可能是经过了某些网关或者负载均衡器这些中间层如果对 TCP 包做了修改或者限制会导致数据包格式被破坏。这时候优先检查网络路径上的中间组件是否有透明代理、七层负载均衡等设备。5.2 配置变更与滚动重启注意事项KRaft 模式下集群配置变更相对安全了一些但滚动重启仍然需要谨慎。一个常见的配置变更是增加新节点比如从 3 节点扩到 5 节点。在 KRaft 模式下先在新节点上安装 Kafka 并生成相同的集群 ID再用 controller.quorum.voters 参数将新节点加入 Quorum之后新节点就可以正常提供服务了。需要特别注意的坑是每个节点配置里的 controller.quorum.voters 都需要更新为最新节点列表。如果你给新节点配置了完整的 voters 列表但旧节点没有更新可能仍然能运行一段时间但一旦某个 Controller 节点触发选举就会出现 Quorum 无法达成一致的情况。滚动重启时还有一个容易被忽略的点是 metadata.log.dir 目录的权限问题。如果以 root 用户启动过 Kafka元数据日志文件的所有者就变成了 root之后切换到普通用户启动时会出现权限错误。这里的排查思路是始终用同一个系统用户管理 Kafka 文件同时注意日志目录的目录权限。还有一点要提醒的是KRaft 模式下不建议直接停掉所有 controller 节点然后想着起来之后就能自己恢复。如果整个集群同时挂掉且所有节点的元数据日志都损坏恢复起来就和 ZK 模式下的全挂场景一样复杂。因此在生产环境至少保证一个节点的元数据日志目录有完整的备份。5.3 读写性能与硬件关系的实测心得日常群里经常有人问“Kafka 单分区写入最大值是多少”、“Kafka 的读写性能极限到底和硬件什么关系”。这个问题的答案其实没有固定值但我实测下来的经验是在高吞吐场景下Kafka 的读写性能主要受三个硬件因素影响磁盘顺序写入速度、网络带宽、CPU 的线程调度能力。磁盘方面Kafka 对顺序写入的利用非常好即使使用的是普通 SSD单分区顺序写也能轻松达到每秒几十万条消息的量级。但如果是随机写入性能会掉得非常明显所以尽量保持 topic 数据在文件系统层面的顺序性。使用独立数据盘和独立元数据盘能有效避免阻塞。网络方面跨可用区的复制带宽是很大的瓶颈。如果你的副本因子是 3且 3 个 ISR 分别在不同可用区那么每次写入都需要把数据复制到 3 个节点网络往返会占用大量带宽。这时候网络带宽就成了性能上限。可以在 broker 侧开启压缩降低网络传输的数据量。CPU 方面Kafka 的每个网络线程负责处理连接和请求解析如果 CPU 核数太少在高并发连接下会出现请求排队的情况。推荐给 Kafka 至少分配 4 核以上如果追求高吞吐8 核起步会更稳妥。针对“读写最大值”这个问题我更愿意给出一个测算思路先通过压测工具比如 kafka-producer-perf-test.sh 和 kafka-consumer-perf-test.sh在自己的硬件配置上打一次基线记录单分区、多分区的最大吞吐量然后根据业务峰值往上预留 30% 的余量。这比网上任何一个所谓的“最大参考值”都靠谱。6. 消息队列选型视角Kafka 与 RabbitMQ、RocketMQ 的取舍6.1 三种消息队列的定位差异消息队列这块Kafka、RabbitMQ、RocketMQ 是中文社区讨论最多的三个。它们设计定位不同适用场景天然有差异。Kafka 的核心设计是分布式日志流它天生适合高吞吐、持久化、流式处理的场景。比如埋点日志收集、订单事件流、实时数仓的 ODS 层这些数据量巨大、要求低延迟上传但不需要复杂路由的场景Kafka 是最自然的选择。它的弱点是消息路由能力弱基本就是按 key 分发到分区没有 RabbitMQ 那种灵活的路由协议。RabbitMQ 是经典的消息代理它的核心优势是路由灵活性。通过 exchange、binding、routing key 的组合你能实现非常细粒度的消息分发。它适合业务系统内部的事件通知、任务调度、解耦场景吞吐量比 Kafka 低但胜在功能丰富、延迟低。还有 RabbitMQ 的延迟队列、死信队列、优先级队列这些能力对业务开发很友好。RocketMQ 从定位上更像是 Kafka 的增强版它在 Kafka 的分布式日志模型之上增加了事务消息、延迟消息、消息轨迹这些企业级特性。金融、电商领域经常拿它做订单状态机的分布式事务消息因为它的事务消息实现是目前消息队列里最成熟的。日志类大流量场景 RocketMQ 也能抗住但配置和管理比 Kafka 复杂一些。6.2 什么时候该用 Kafka什么时候该选别的选型不应该“哪个火就用哪个”而是根据你的核心诉求决定。我一般来说会分成几类场景来判断。如果你要做的是高吞吐日志和事件流比如每秒上万条以上的埋点数据请直接考虑 Kafka。它在这个场景下性能最强、生态最丰富Flink、Spark Streaming 等流处理框架对 Kafka 的支持也最完善。如果你的场景是业务系统内部的解耦比如 A 服务完成订单后通知 B 服务、C 服务做后续处理消息量不算很大但对路由灵活性和运维简便性有要求RabbitMQ 或者 RocketMQ 更合适。RabbitMQ 在轻量级场景下部署简单RocketMQ 在事务消息和可靠性上有优势。如果你需要事务消息保证分布式系统的一致性或者在消息层面实现类似“订单创建后 30 分钟未支付自动关单”这种定时任务能力RocketMQ 的延迟消息和事务消息实现可以直接开箱即用。Kafka 在这块支持相对基础需要你自己在外围实现。还有一个场景是 Kafka Connect 和数据管道。如果你想把数据库变更实时同步到数仓或者搜索集群Kafka 的 Connect 生态有大量现成连接器比自己在 RabbitMQ 里做一套数据管道省事得多。最终落到 KRaft 模式上如果你决定用 Kafka那么现阶段新部署集群务必用 KRaft 模式。ZooKeeper 模式虽然还能用但已经是维护模式社区新特性只会优先在 KRaft 模式上迭代。对于已有 ZK 模式的存量集群可以按照官方提供的迁移工具逐步过渡不建议一步到位直接切换毕竟涉及元数据兼容和客户端协议的变更稳妥为主。我把集群全部迁移到 KRaft 模式之后最大的感受是日常运维里“ZooKeeper 和 Kafka 数据不一致”这类玄学问题彻底消失了Controller 切换速度和元数据下发效率都明显提升。如果你还没接触过 KRaft 模式建议先在测试环境里搭一个 3 节点集群跑一遍把元数据目录、Controller 选举、滚动重启这些场景都亲手试一次。等你习惯了“没有 ZK”的 Kafka 集群再回头维护老架构时会明显感觉 KRaft 才是 Kafka 该有的样子。
返回列表