Kafka中的coordinator

本文介绍了Kafka在0.9版本后如何通过中心Coordinator实现Rebalance,避免Zookeeper的问题。详细讨论了触发Rebalance的五种条件,以及Consumer在Rebalance过程中的角色,包括启动时找寻Coordinator、发送HeartbeatRequest、处理非法Generation错误码等步骤。同时,概述了Consumer的状态机和故障检测机制。
部署运行你感兴趣的模型镜像

在0.9以前的client api中,consumer是要依赖Zookeeper的。因为同一个consumer group中的所有consumer需要进行协同,进行下面所讲的rebalance。

但是因为zookeeper的“herd effect”与“split brain”,导致一个group里面,不同的consumer拥有了同一个partition,进而会引起消息的消费错乱。为此,在0.9中,不再用zookeeper,而是Kafka集群本身来进行consumer之间的同步。(注:herd effect任何Broker或者Consumer的增减都会触发所有的Consumer的Rebalance;split brain:每个Consumer分别单独通过Zookeeper判断哪些Broker和Consumer 宕机了,那么不同Consumer在同一时刻从Zookeeper“看”到的View就可能不一样,这是由Zookeeper的特性决定的,这就会造成不正确的Reblance尝试。

所谓rebalance,就是在某些条件下,partition要在consumer中重新分配。那哪些条件下,会触发rebalance呢? 
条件1:有新的consumer加入 
条件2:旧的consumer挂了 
条件3:coordinator挂了,集群选举出新的coordinator 
条件4:topic的partition新加 
条件5:consumer调用unsubscrible(),取消topic的订阅

如何通过中心Coordinator实现Rebalance

成功Rebalance的结果是,被订阅的所有Topic的每一个Partition将会被Consumer Group内的一个(有且仅有一个)Consumer拥有。每一个Broker将被选举为某些Consumer Group的Coordinator。某个Cosnumer Group的Coordinator负责在该Consumer Group的成员变化或者所订阅的Topic的Partititon变化时协调Rebalance操作。

Consumer

1) Consumer启动时,先向Broker列表中的任意一个Broker发送ConsumerMetadataRequest,并通过 ConsumerMetadataResponse获取它所在Group的Coordinator信息。ConsumerMetadataRequest 和ConsumerMetadataResponse的结构如下

ConsumerMetadataRequest
{
  GroupId                => String
}

ConsumerMetadataResponse
{
  ErrorCode              => int16
  Coordinator            => Broker
}

2)Consumer连接到Coordinator并发送 HeartbeatRequest,如果返回的HeartbeatResponse没有任何错误码,Consumer继续fetch数据。若其中包含 IllegalGeneration错误码,即说明Coordinator已经发起了Rebalance操作,此时Consumer停止fetch数据,commit offset,并发送JoinGroupRequest给它的Coordinator,并在JoinGroupResponse中获得它应该拥有的所有 Partition列表和它所属的Group的新的Generation ID。此时Rebalance完成,Consumer开始fetch数据。相应Request和Response结构如下

HeartbeatRequest
{
  GroupId                => String
  GroupGenerationId      => int32
  ConsumerId             => String
}

HeartbeatResponse
{
  ErrorCode              => int16
}

JoinGroupRequest
{
  GroupId                     => String
  SessionTimeout              => int32
  Topics                      => [String]
  ConsumerId                  => String
  PartitionAssignmentStrategy => String
}

JoinGroupResponse
{
  ErrorCode              => int16
  GroupGenerationId      => int32
  ConsumerId             => String
  PartitionsToOwn        => [TopicName [Partition]]
}
TopicName => String
Partition => int32

Consumer状态机

Down:Consumer停止工作

Start up & discover coordinator:Consumer检测其所在Group的Coordinator。一旦它检测到Coordinator,即向其发送JoinGroupRequest。

Part of a group:该状态下,Consumer已经是该Group的成员,并周期性发送HeartbeatRequest。如 HeartbeatResponse包含IllegalGeneration错误码,则转换到Stopped Consumption状态。若连接丢失,HeartbeatResponse包含NotCoordinatorForGroup错误码,则转换到 Rediscover coordinator状态。

Rediscover coordinator:该状态下,Consumer不停止消费而是尝试通过发送ConsumerMetadataRequest来探测新的Coordinator,并且等待直到获得无错误码的响应。

Stopped consumption:该状态下,Consumer停止消费并提交offset,直到它再次加入Group。

故障检测机制

Consumer成功加入Group后,Consumer和相应的Coordinator同时开始故障探测程序。Consumer向 Coordinator发起周期性的Heartbeat(HeartbeatRequest)并等待响应,该周期为 session.timeout.ms/heartbeat.frequency。若Consumer在session.timeout.ms内未收到 HeartbeatResponse,或者发现相应的Socket channel断开,它即认为Coordinator已宕机并启动Coordinator探测程序。若Coordinator在 session.timeout.ms内没有收到一次HeartbeatRequest,则它将该Consumer标记为宕机状态并为其所在Group触发一次Rebalance操作。

Coordinator Failover过程中,Consumer可能会在新的Coordinator完成Failover过程之前或之后发现新的Coordinator并向其发送HeatbeatRequest。对于后者,新的Cooodinator可能拒绝该请求,致使该Consumer重新探测Coordinator并发起新的连接请求。如果该Consumer向新的Coordinator发送连接请求太晚,新的Coordinator可能已经在此之前将其标记为宕机状态而将之视为新加入的Consumer并触发一次Rebalance操作。


您可能感兴趣的与本文相关的镜像

Qwen-Image-Edit-2509

Qwen-Image-Edit-2509

图片编辑
Qwen

Qwen-Image-Edit-2509 是阿里巴巴通义千问团队于2025年9月发布的最新图像编辑AI模型,主要支持多图编辑,包括“人物+人物”、“人物+商品”等组合玩法

ta@10-102-21-72:/app/ta#[2025-11-30 15:07:58,504] INFO [GroupCoordinator 0]: Member consumer-ta-system-1-6a5ce779-f148-49cd-a80e-493c5fd9fb07 in group ta-system has failed, removing it from the group (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:58,505] INFO [GroupCoordinator 0]: Preparing to rebalance group ta-system in state PreparingRebalance with old generation 1 (__consumer_offsets-27) (reason: removing member consumer-ta-system-1-6a5ce779-f148-49cd-a80e-493c5fd9fb07 on heartbeat expiration) (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:58,505] INFO [GroupCoordinator 0]: Member consumer-ta-system-2-26c2148c-bc0b-44c2-beca-ed1959310432 in group ta-system has failed, removing it from the group (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,131] INFO [GroupCoordinator 0]: Member consumer-1.10.102.21.72.8081-7-a6d9374c-f30c-441a-81d1-0d8e6ee24087 in group 1.10.102.21.72.8081 has failed, removing it from the group (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,132] INFO [GroupCoordinator 0]: Preparing to rebalance group 1.10.102.21.72.8081 in state PreparingRebalance with old generation 1 (__consumer_offsets-26) (reason: removing member consumer-1.10.102.21.72.8081-7-a6d9374c-f30c-441a-81d1-0d8e6ee24087 on heartbeat expiration) (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,132] INFO [GroupCoordinator 0]: Group 1.10.102.21.72.8081 with generation 2 is now empty (__consumer_offsets-26) (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,140] INFO [GroupCoordinator 0]: Member consumer-ta-system-6-4c313058-e169-4e8e-9a1a-a5cbbb7ff564 in group ta-system has failed, removing it from the group (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,141] INFO [GroupCoordinator 0]: Member consumer-ta-system-3-17359b5c-8a72-4771-9337-547610041773 in group ta-system has failed, removing it from the group (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,141] INFO [GroupCoordinator 0]: Group ta-system with generation 2 is now empty (__consumer_offsets-27) (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,142] INFO [GroupCoordinator 0]: Member consumer-ta-system-0-5-e4b4818a-7859-4ee9-86d4-10a6f84ba63a in group ta-system-0 has failed, removing it from the group (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,142] INFO [GroupCoordinator 0]: Preparing to rebalance group ta-system-0 in state PreparingRebalance with old generation 1 (__consumer_offsets-0) (reason: removing member consumer-ta-system-0-5-e4b4818a-7859-4ee9-86d4-10a6f84ba63a on heartbeat expiration) (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,142] INFO [GroupCoordinator 0]: Member consumer-ta-system-0-4-5b716cbf-c54c-4489-87ed-0f032b5d7787 in group ta-system-0 has failed, removing it from the group (kafka.coordinator.group.GroupCoordinator) [2025-11-30 15:07:59,142] INFO [GroupCoordinator 0]: Group ta-system-0 with generation 2 is now empty (__consumer_offsets-0) (kafka.coordinator.group.GroupCoordinator) 什么意思
最新发布
12-01
### 消费者成员失败 消费者成员失败指的是 Kafka 消费者组中的某个消费者实例无法正常工作的情况。可能的原因包括网络故障、消费者进程崩溃、资源耗尽等。当消费者成员失败时,它将无法继续从 Kafka 主题的分区中消费消息,也不能提交位移数据。例如,消费者可能因为网络中断,无法与 Kafka Broker 进行通信,从而导致无法接收新消息和提交已处理消息的偏移量。 ### 消费者成员移除 消费者成员移除通常是因为消费者被组协调器(Group Coordinator)主动移除出消费者组。当消费者发起提交偏移量的请求,但 Broker 拒绝该请求,原因可能是消费者不在组内,即“被踢出组”,这是消费者成员移除的常见表现。消费者长时间不向组协调器发送心跳、处理消息超时等情况,都可能导致被组协调器判定为失败并移除出组 [^2]。 ### 组重新平衡 组重新平衡是 Kafka 消费者组在某些情况下进行的一种操作,目的是重新分配分区给消费者组内的成员。当有新的消费者加入组、已有消费者离开组(如成员失败或被移除)、主题的分区数发生变化时,都会触发组重新平衡。在重新平衡过程中,消费者组内的每个消费者会停止消费消息,等待重新分配分区。重新分配完成后,消费者会从新分配的分区开始继续消费消息。例如,原本由消费者 A 消费的分区,在重新平衡后可能会分配给消费者 B 进行消费。 在 Kafka 中,位移提交是由消费端负责的,Kafka 只负责将位移数据保管到 `__consumer_offsets` 主题中。`__consumer_offsets` 中的消息保存了每个消费组某一时刻提交的 offset 信息。消费者需要为分配给它的每个分区提交各自的位移数据,以记录消费进度 [^1][^5]。 ### 示例代码 以下是一个简单的 Kafka 消费者示例代码,展示了基本的消费者配置和消费逻辑: ```java import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.consumer.KafkaConsumer; import org.apache.kafka.common.serialization.StringDeserializer; import java.time.Duration; import java.util.Collections; import java.util.Properties; public class KafkaConsumerExample { public static void main(String[] args) { Properties props = new Properties(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); props.put(ConsumerConfig.GROUP_ID_CONFIG, "test-group"); props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props); consumer.subscribe(Collections.singletonList("test-topic")); try { while (true) { ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100)); for (ConsumerRecord<String, String> record : records) { System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value()); } } } finally { consumer.close(); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值