Kafka核心组件之协调器
协调器介绍
kafka引入协调器有其历史过程,原来consumer信息依赖于zookeeper存储,当代理或消费者发生变化时,引发消费者平衡,此时消费者之间是互不透明的,每个消费者和zookeeper单独通信,容易造成羊群效应和脑裂问题。
为了解决这些问题,kafka引入了协调器:
- 消费者端引入消费者协调器(ConsumerCoordinator)
每个consumer实例化时,都会创建ConsumerCoordinator实例,负责同一个消费组下各个消费者和服务端组协调器之间的通信。 - 服务端引入组协调器(GroupCoordinator)
每个broker启动的时候,都会创建GroupCoordinator实例,管理部分消费组(集群负载均衡)和组下每个消费者消费的偏移量(offset)
消费者协调器
消费者协调器,可以看作是消费者做操作的代理类(其实并不是),消费者很多操作通过消费者协调器进行处理。
消费者协调器主要负责如下工作:
- 更新消费者缓存的MetaData
- 向组协调器申请加入组
- 消费者加入组后的相应处理
- 请求离开消费组
- 向组协调器提交偏移量
- 通过心跳,保持组协调器的连接感知
- 被组协调器选为leader的消费者的协调器,负责消费者分区分配。分配结果发送给组协调器
- 非leader的消费者,通过消费者协调器和组协调器同步分配结果
组协调器
组协调器负责处理消费者协调器发过来的各种请求。
组协调器主要提供如下功能:
- 在与之连接的消费者中选举出消费者leader
- 下发leader消费者返回的消费者分区分配结果给所有的消费者
- 管理消费者的消费偏移量提交,保存在kafka的内部主题中
- 和消费者心跳保持,知道哪些消费者已经死掉,组中存活的消费者是哪些
消费偏移量管理
消费者消费时,会在本地维护消费到的位置(offset),就是偏移量,这样下次消费才知道从哪里开始消费。如果整个环境没有变化,这样做就足够了。但一旦消费者平衡操作或者分区变化后,消费者不再对应原来的分区,而每个消费者的offset也没有同步到服务器,这样就无法接着前任的工作继续进行了。
因此只有把消费偏移量定期发送到服务器,由GroupCoordinator集中式管理,分区重分配后,各个消费者从GroupCoordinator读取自己对应分区的offset,在新的分区上继续前任的工作。
Consumer Rebalance机制
对于 Consumer Group 来说,可能随时都会有 Consumer 加入或退出,那么 Consumer 列表的变化必定会引起 Partition 的重新分配,这个分配过程就叫做 Consumer Rebalance。
触发消费者rebalance的常见情况:
- consumer所在服务重启或宕机
- 动态给topic增加了分区
- 消费组订阅了更多的topic
Rebalance过程
第一阶段:选择组协调器
每个consumer group都会选择一个broker作为自己的组协调器coordinator,负责监控这个消费组里的所有消费者的心跳,以及判断是否宕机,然后开启消费者rebalance。
consumer group中的每个consumer启动时会向kafka集群中的某个节点发送FindCoordinatorRequest请求来查找对应的组协调器GroupCoordinator,并跟其建立网络连接。
组协调器选择方式:
通过如下公式可以选出consumer消费的offset要提交到__consumer_offsets的哪个分区,这个分区leader对应的broker就是这个consumer group的coordinator.
公式:
hash(consumer group id) % __consumer_offsets主题的分区数
第二阶段:加入消费组JOIN GROUP
在成功找到消费组所对应的GroupCoordinator之后就进入加入消费组的阶段,在此阶段的消费者会向GroupCoordinator发送JoinGroupRequest请求,并处理响应。
然后GroupCoordinator从一个consumer group中选择第一个加入group的consumer作为leader(消费组协调器),把consumer group情况发送给这个leader,接着这个leader会负责制定分区方案。
第三阶段:SYNC GROUP
consumer leader通过给GroupCoordinator发送SyncGroupRequest,接着GroupCoordinator就把分区方案下发给各个consumer,他们会根据指定分区的leader broker进行网络连接以及消息消费。
Rebalance分区分配策略
主要有三种rebalance的策略:range、round-robin、sticky。
默认情况为range分配策略,假设一个主题有10个分区(0-9),现在有三个consumer消费:
- range策略:按照分区序号排序
假设 n=分区数/消费者数量=3,m=分区数%消费者数量 = 1,那么前m个消费者每个分配n+1个分区,后面的(消费者数量-m)个消费者每个分配n个分区。比如分区0-3给一个consumer,分区4-6给一个consumer,分区7-9给一个consumer。 - round-robin策略:轮询分配
比如分区0、3、6、9给一个consumer,分区1、4、7给一个consumer,分区2、5、8给一个consumer。 - sticky策略:在rebalance的时候,需要保证如下两个原则
- 分区的分配要尽可能均匀;
- 分区的分配尽可能与上次分配的保持相同。