由于kafka topic的某一个分区只能同时被一个消费者消费,据官方介绍是因为两个消费者同时消费一个分区就不能保证单个分区消息的顺序性了。当消费者,broker,topic分区 的数目发生变化时,consumer都可能发生Rebalance操作,总结如下:
1.有消费者下线,主要是消费这个长时间未向GroupCoordinator发送心跳请求,GroupCoordinator认为消费者下线
2.有新的消费者加入 Consumer Group,需要重新分配topic消费分区
3.有消费者退出 Consumer Group
4.consumer 消费者 订阅的topic 的分区数量发生变化
5.消费者取消对某一个topic的订阅,主要是调用 unsubscrible()方法
老版消费者是用scala实现,Rebalance操作主要是通过 Zookeeper来实现,每个broker都会在zk上注册监听,每个消费者都会在zk上生成订阅的topic以及消费分区节点,当 消费者,broker,topic分区 的数目发生变化时 都可以通过zk上的监听来触发Rebalance操作,这种设计严重依赖zk,容易造成 “羊群效应”和 “脑裂”。新版的消费者用java实现,对Rebalance操作进行了重新设计,主要是增加和 GroupCoordinator和ConsumerCoordinator两个类,用于协调consumer和kafka集群的Rebalance操作,其主要流程如下:
从上图可以看到,Consumer 的Rebalance操作主要是分为三个阶段:
第一阶段主要是查找GroupCoordinator的过程, 消费者向集群中负载最低的节点发送GroupCoordinatorRequest,kafka集群响应GroupCoordinator 的节点信息,包括IP和PORT等信息。
第二阶段只要主要是向GroupCoordinator节点发送JoingroupRequest,请求加入Group,GroupCoordinator节点会根据一定的算法选举出消费者对应的Leader节点和Follower节点,并根据JoingroupRequest请求中包含的各个消费者支持的分区分配方式返回给Leader节点分区分配方式以及所有消费者的集合,同时会返回各个消费者对应的memberId
第三阶段主要是消费者与GroupCoordinater的同步阶段,Leader节点根据第二阶段获取的消费者分配策略以及所有消费者的集合对和消费者做消费分区分配,并将分配信息通过SyncGroup请求的方式同步给GroupCoordinator,Follower节点通过发送SyncGroup请求同步自身对应的消费分区信息
通过上面的三个步骤,就完成了Consumer Group的Rebalance操作,ConsumerGroup通过 ConsumerCoordinator对象定期向GroupCoordinator 发送心跳请求,以确定GroupCoordinator节点是否正常,如果心跳请求响应异常就会重新发起Rebalance操作。
下一步我们将详细介绍消费者消费过程。