Kafka新版本重大更新,发布4.0!!

Apache Kafka 4.0 是一个里程碑式的版本,带来了多项重大更新,尤其是在架构、性能和功能扩展方面。以下是 Kafka 4.0 的主要更新及其原理的详细介绍:


1. 完全移除 ZooKeeper,默认使用 KRaft 模式

更新内容

  • Kafka 4.0 彻底移除了对 ZooKeeper 的依赖,默认运行在 KRaft(Kafka Raft)模式下。KRaft 是 Kafka 自带的元数据管理机制,基于 Raft 共识协议实现。
  • ZooKeeper 在之前的版本中负责元数据存储、领导者选举和集群协调,而现在这些功能完全由 Kafka 内部的控制器(Controller)接管。

原理

  • Raft 协议:KRaft 使用 Raft 共识算法来管理元数据日志的复制和一致性。Raft 将集群分为领导者(Leader)和跟随者(Follower),通过日志复制和投票机制确保数据一致性。

    • 领导者选举:当控制器节点宕机时,KRaft 通过投票选出新的领导者,投票基于节点的日志状态(即谁拥有最新的日志)。
    • 日志复制:元数据变更(如主题创建、分区分配)被记录为日志条目,由领导者广播到跟随者,确保所有节点状态一致。
  • 元数据存储:元数据不再存储在 ZooKeeper 的 ZNode 树中,而是以日志形式存储在 Kafka 自己的日志文件中(通常位于磁盘上的元数据日志目录)。

  • 控制器集群:KRaft 引入了一个小型控制器集群(通常 3-5 个节点),这些节点共同维护元数据并处理集群管理任务。

优势

  • 消除了 ZooKeeper 的外部依赖,简化了部署和运维。
  • 减少了 ZooKeeper 的性能瓶颈(如高负载下的延迟),元数据操作更快。
  • 提高了可扩展性,控制器集群可以动态调整规模。

注意事项

  • 升级到 4.0 前,需从 ZooKeeper 模式迁移到 KRaft(建议先升级到 3.7 或 3.8 并完成迁移)。

2. KIP-848:新一代消费者组重平衡协议

更新内容

  • Kafka 4.0 正式引入了新的消费者组重平衡协议,显著提升了消费者组在分区重新分配时的性能和稳定性。

原理

  • 传统重平衡问题:旧协议(基于"停止世界"模型)在重平衡时会暂停所有消费者,导致服务中断时间较长,尤其是在大规模消费者组中。

  • 新协议设计

    • 增量重平衡:新协议允许消费者在重平衡期间继续处理未被重新分配的分区,而不是全部暂停。
    • 协调者优化:组协调者(Group Coordinator)使用更高效的状态机和通信机制,减少了重平衡的协调开销。
    • 分区分配策略:通过客户端和协调者之间的双向通信,分区分配更加智能,支持动态调整而无需全量重新分配。
  • 实现细节

    • 消费者客户端定期向协调者发送心跳信号,报告其状态。
    • 协调者根据心跳和组成员变化,逐步调整分区分配,而不是一次性重新计算。

优势

  • 重平衡时间从秒级缩短到毫秒级,减少了服务中断。
  • 在大规模消费者组(数百或数千消费者)中表现更优。
  • 提高了消费者应用的可用性和吞吐量。

3. KIP-932:Kafka 队列(早期访问)

更新内容

  • Kafka 4.0 引入了队列语义的支持(早期访问阶段),允许 Kafka 直接支持点对点消息传递模式,而不仅仅是发布-订阅模型。

原理

  • 传统模型:Kafka 的主题(Topic)基于发布-订阅模型,消息被所有订阅者消费。

  • 队列模式

    • 在队列模式下,一个消费者组内的消息只被一个消费者处理,类似于传统消息队列(如 RabbitMQ)。
    • 通过在消费者组协议中引入"独占消费"逻辑实现:当一个消费者从分区消费消息时,其他消费者被阻止访问该分区。
  • 实现细节

    • 队列模式通过配置主题或消费者组的属性启用。
    • 分区分配策略被调整为"单一消费者分配",确保消息的顺序性和独占性。

优势

  • 扩展了 Kafka 的使用场景,适用于需要队列语义的工作负载(如任务分发)。
  • 无需额外部署其他消息队列系统,统一技术栈。

当前限制

  • 作为早期访问功能,尚不完全稳定,可能在后续版本中进一步完善。

4. KIP-966:Eligible Leader Replicas(预览)

更新内容

  • 引入"合格领导副本"(ELR)概念,作为同步副本(ISR)的子集,确保领导者选举时数据完整性。

原理

  • 背景:在 Kafka 中,分区的领导者负责处理读写请求,同步副本(ISR)保持与领导者一致。当领导者宕机时,从 ISR 中选举新领导者,但可能存在数据未完全同步的风险。

  • ELR 定义:ELR 是 ISR 的一个子集,只有那些日志达到高水位线(High-Watermark,即所有副本都确认的偏移量)的副本才被认为是"合格的"。

  • 选举过程

    • 当领导者失效时,控制器只从 ELR 中选择新领导者。
    • 如果没有合格副本,则暂停选举,直到副本同步完成。

优势

  • 防止因领导者选举导致的数据丢失或不一致。
  • 提高了高可用性场景下的数据可靠性。

当前状态

  • 预览功能,可能在未来版本中成为默认行为。

5. KIP-996:Pre-Vote 机制(预览)

更新内容

  • 在 KRaft 模式下引入"预投票"机制,优化领导者选举过程。

原理

  • 传统 Raft 选举:当领导者失效时,所有节点直接进入投票阶段,可能导致频繁的选举冲突。

  • Pre-Vote 机制

    • 在正式投票前,节点先进行"预投票"阶段,询问其他节点是否支持其成为领导者。
    • 只有在获得足够支持后,节点才会发起正式投票。
  • 实现细节

    • 预投票不更改节点状态,仅用于收集信息。
    • 减少了因网络分区或短暂故障导致的无效选举。

优势

  • 提升了 KRaft 控制器集群的稳定性。
  • 减少了不必要的领导者切换,降低了集群抖动。

6. 其他重大更新

  • Java 版本升级

    • 客户端要求 Java 11,经纪人要求 Java 17,利用新版 Java 的性能优化(如垃圾回收改进)和安全性。
  • 日志框架迁移到 Log4j2

    • 替换 Log4j,解决安全漏洞,并提供更灵活的日志配置。
  • 移除过时功能

    • 删除消息格式 v0/v1 和其他标记为过时的 API,精简代码库。

7. Docker部署尝鲜

下面是在docker环境中部署Kafka 4.0, 该集群包含3个控制节点、2个Broker节点、1个kafdrop仪表盘:

yaml 复制代码
services:
  controller-1:
    image: 'apache/kafka:4.0.0'
    restart: "always"
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: controller
      KAFKA_LISTENERS: CONTROLLER://:9093
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@controller-1:9093,2@controller-2:9093,3@controller-3:9093
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
    networks:
      - kfk-network
  controller-2:
    image: 'apache/kafka:4.0.0'
    restart: "always"
    environment:
      KAFKA_NODE_ID: 2
      KAFKA_PROCESS_ROLES: controller
      KAFKA_LISTENERS: CONTROLLER://:9093
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@controller-1:9093,2@controller-2:9093,3@controller-3:9093
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
    networks:
      - kfk-network
    depends_on:
      - controller-1
  controller-3:
    image: 'apache/kafka:4.0.0'
    restart: "always"
    environment:
      KAFKA_NODE_ID: 3
      KAFKA_PROCESS_ROLES: controller
      KAFKA_LISTENERS: CONTROLLER://:9093
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@controller-1:9093,2@controller-2:9093,3@controller-3:9093
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
    networks:
      - kfk-network
    depends_on:
      - controller-1
  broker-1:
    image: 'apache/kafka:4.0.0'
    restart: "always"
    ports:
      - 39092:19092
    environment:
      KAFKA_NODE_ID: 4
      KAFKA_PROCESS_ROLES: broker
      KAFKA_LISTENERS: 'INTERNAL://:9092,EXTERNAL://:19092'
      KAFKA_ADVERTISED_LISTENERS: 'INTERNAL://broker-1:9092,EXTERNAL://192.168.221.128:39092'
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@controller-1:9093,2@controller-2:9093,3@controller-3:9093
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 2
    networks:
      - kfk-network
    depends_on:
      - controller-1
      - controller-2
      - controller-3
  broker-2:
    image: 'apache/kafka:4.0.0'
    restart: "always"
    ports:
      - 29092:19092
    environment:
      KAFKA_NODE_ID: 5
      KAFKA_PROCESS_ROLES: broker
      KAFKA_LISTENERS: 'INTERNAL://:9092,EXTERNAL://:19092'
      KAFKA_ADVERTISED_LISTENERS: 'INTERNAL://broker-2:9092,EXTERNAL://192.168.221.128:29092'
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@controller-1:9093,2@controller-2:9093,3@controller-3:9093
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 2
    networks:
      - kfk-network
    depends_on:
      - controller-1
      - controller-2
      - controller-3
  kafdrop:
    image: obsidiandynamics/kafdrop
    restart: "no"
    ports:
      - "9000:9000"
    environment:
      KAFKA_BROKERCONNECT: "broker-1:9092,broker-2:9092"
    depends_on:
      - broker-1
      - broker-2
    networks:
      - kfk-network
networks:
  kfk-network:
    name: kfk-network
    external: true

总结与原理核心

Kafka 4.0 的核心更新围绕"简化架构"和"提升性能"展开:

  • KRaft 通过 Raft 协议内嵌元数据管理,消除了 ZooKeeper 的外部依赖,原理上是将分布式一致性逻辑整合到 Kafka 内部。
  • 消费者组重平衡 通过增量分配和优化协调,减少了停机时间,核心在于分布式状态机的改进。
  • 队列支持ELR/Pre-Vote 则扩展了功能并增强了可靠性,基于现有协议的微调和扩展。

这些更新的原理都建立在分布式系统理论(如 Raft 共识、分区分配优化)之上,旨在让 Kafka 更高效、更易用。

相关推荐
蚂蚁背大象36 分钟前
Rust 所有权系统是为了解决什么问题
后端·rust
子玖2 小时前
go实现通过ip解析城市
后端·go
Java不加班2 小时前
Java 后端定时任务实现方案与工程化指南
后端
心在飞扬3 小时前
RAG 进阶检索学习笔记
后端
Moment3 小时前
想要长期陪伴你的助理?先从部署一个 OpenClaw 开始 😍😍😍
前端·后端·github
Das1_3 小时前
【Golang 数据结构】Slice 底层机制
后端·go
得物技术3 小时前
深入剖析Spark UI界面:参数与界面详解|得物技术
大数据·后端·spark
古时的风筝3 小时前
花10 分钟时间,把终端改造成“生产力武器”:Ghostty + Yazi + Lazygit 配置全流程
前端·后端·程序员
Cache技术分享3 小时前
340. Java Stream API - 理解并行流的额外开销
前端·后端