弃而舍之,朽木不折。 弃而不舍,金石可镂。
——战国:荀子的《劝学》
前言
Kafka系列第二期【(二)消息队列-Kafka核心概念(相知)】有讲到分区的概念,在这里分享下分区再均衡,这个在Kafka核心里来说是狠招那个
分区再均衡是什么
Kafka一个分区可以被不同消费者群组的消费者消费,如果某个消费者宕机或crashes或有新的消费者加入,那么就会分区协调者会重新分配分区,分区的所有权从一个消费者转移到另外一个消费者,这就是分区再均衡。如果新增分区,也会触发分区再均衡。
分区再均衡策略
RangeAssignor
这种只针对消费者订阅主题topic的单个主题topic,也是Kafka的默认分配策略。
partition.assignment.strategy对应的策略是org.apache.kafka.clients.consumer.RangeAssignor
- 同一个主题的所有分区按照序号来排序,存于TP(topic partition简称)
- 同一个消费者群组下的所有消费者按照数据字典(字母)来排序,存于CG(consumer group简称)
- TP分区数量除以CG消费者数量,如果除不尽,则多余的放到第一个消费者消费
从上图可以看出,如果topic越多,C1消费者越来越多,这个明显是RangeAssignor册率的一个弊端。
RoundRobinAssignor
这种只针对所有topic所有分区进行分配,但也要满足两个条件:
- 在实例化的时候,每个消费者给每个topic相同的流数量stream.nums
- 每个消费者分配的topic是相同的
Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
topicCountMap.put(topic, Integer类型的流数量);
Map<String, List<KafkaStream<byte[], byte[]>>> consumerMap = consumer.createMessageStreams(topicCountMap);
partition.assignment.strategy对应的策略是``org.apache.kafka.clients.consumer.RoundRobinAssignor
- 所有topic+partition转string,然后进行hash排序
- 所有消费者按照数据字典(字母)来排序
- 然后轮询地将分区分配给消费者
StickAssignor
该分配策略从kafka0.11.x版本开始有的。stick,中文含义粘性
,它的作用是:
- 分区分配尽量均衡,主题分区数量相差最大为1个
- 分区分配尽量保持和上次分区保持一致
- 如果第一点和第二点冲突,则第一点优先考虑
分区再均衡过程
- 成员像协调者发送心跳检测,判断是否存活
- 协调者ACK
- 成员请求加入消费者群组 (joinGroup请求)
- 协调者ACK加入成功与否
- 成员请求分区再均衡SyncGroup
- 协调者ACK reblance成功与否(SyncGroup响应)