Kafka中涉及到选主的地方比较多,所以也比较复杂,这里做一下总结。 Kafka中的选举大致可以分为三大类:控制器的选举、分区leader的选举以及消费者相关的选举
controller选举
集群控制器组件(BrokerController): 它是 Kafka 的核心组件。它的主要作用是在 ZooKeeper 的帮助下管理和协调整个 Kafka 集群,集群中的每个 broker 都可以称为 controller,但是在 Kafka 集群启动后,只有一个 broker 会成为 Controller 。 Controller Broker的主要职责有很多,主要是一些管理行为,主要包括以下几个方面: ? 创建、删除主题,增加分区并分配leader分区 ? 集群Broker管理(新增 Broker、Broker 主动关闭、Broker 故障) ? preferred leader选举
分区重分配Kafka是基于zookeeper的,controller的选择也是在zookeeper上完成的。 Kafka 当前选举控制器的规则是:Kafka 集群中第一个启动的 broker 通过在 ZooKeeper 里创建一个临时节点 /controller 让自己成为 controller 控制器。其他 broker 在启动时也会尝试创建这个节点,但是由于这个节点已存在,所以后面想要创建 /controller 节点时就会收到一个 节点已存在 的异常。然后其他 broker 会在这个控制器上注册一个 ZooKeeper 的 watch 对象,/controller节点发生变化时,其他 broker 就会收到节点变更通知。这种方式可以确保只有一个控制器存在。那么只有单独的节点一定是有个问题的,那就是单点问题。
如果控制器关闭或者与 ZooKeeper 断开链接,ZooKeeper 上的临时节点就会消失。集群中的其他节点收到 watch 对象发送控制器下线的消息后,其他 broker 节点都会尝试让自己去成为新的控制器。其他节点的创建规则和第一个节点的创建原则一致,都是第一个在 ZooKeeper 里成功创建控制器节点的 broker 会成为新的控制器,那么其他节点就会收到节点已存在的异常,然后在新的控制器节点上再次创建 watch 对象进行监听。
分区leader的选举
? Topic:Kafka 中的消息以 Topic 为单位进行划分,生产者将消息发送到特定的 Topic,而消费者负责订阅 Topic 的消息并进行消费。
?Partition:Topic 是一个逻辑的概念,它可以细分为多个分区,每个分区只属于单个主题。同一个主题下不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset)。
大致关系: Kafka实现高可用的方式是冗余副本,也就是每个分区只会有一个leader对外提供读写服务,其余broker上副本向leader同步数据。这样就涉及一个分区leader的选举
创建分区可以指定leader。如果不指定,则为分区的第一个副本,显然当leader宕机后不能使用这种选主方法。
ISR
kafka副本存在与leader不同步的风险,那么哪些副本是同步的,如何辨别?基于这个想法,kafka引入了ISR(a set of In-Sync Replicas),副本集合。ISR中的副本都是与Leader同步的副本,相反,不在ISR中的追随者副本被认为是与Leader不同步的。那么ISR到底需要满足什么条件才能进入呢。
broker上的消息消费使用了偏移量来标记,通过查看每个跟随者请求的最新偏移量,首领就会知道每个跟随者复制的进度。同时跟随者会对leader进行新消息的请求,如果跟随者在 10s 内没有请求任何消息,或者虽然跟随者已经发送请求,但是在 10s 内没有收到消息,就会被认为是不同步的。如果一个副本没有与领导者同步,那么在领导者掉线后,这个副本将不会称为领导者,因为这个副本的消息不是全部的,跟随者副本就会从 ISR 被剔除。倘若该副本后面慢慢地追上了领导者的进度,那么它是能够重新被加回 ISR 的。这也表明,ISR 是一个动态调整的集合,而非静态不变的。
所以如果leader宕机,Controller会从ISR中选择下一个分区Leader,这里还有个问题,ISR是个集合,是可能为空的。
Unclean 领导者选举
既然ISR可以动态调整,那么就会出现ISR为空的情况。ISR为空的情况就代表Leader副本也挂掉了。那么kafka就需要重新选举新的Leader。 那么该怎么选举Leader呢?
- kafka把所有不在ISR的存活副本都成为非同步副本。
- 通常来说,非同步副本落后Leader太多,因此,如果选择这些副本为新的Leader,就可能出现数据的丢失。在kafka,选举Leader这种过程被成为Unclean。由Broker端参数unclean.leader.election.enable控制是否允许Unclean领导者选举。
- 开启 Unclean 领导者选举可能会造成数据丢失,但好处是,它使得分区 Leader 副本一直存在,不至于停止对外提供服务,因此提升了高可用性。反之,禁止 Unclean 领导者选举的好处在于维护了数据的一致性,避免了消息丢失,但牺牲了高可用性。
可以根据你的实际业务场景决定是否开启 Unclean 领导者选举。不过并不建议开启它,毕竟我们还可以通过其他的方式来提升高可用性。如果为了这点儿高可用性的改善,牺牲了数据一致性,那就非常不值当了。
消费者leader选举
群组协调器(Coordinator):群组协调器是一个能够从消费者群组中收到所有消费者发送心跳消息的 broker。群组协调器可以满足 JoinGroup 请求并提供有关消费者组的元数据信息,例如分配和偏移量。群组协调器还有权知道所有消费者的心跳,
消费者领导者: 每个消费者群组中都有一个领导者,负责分区消费策略的选择
消费者leader的选择比较简单,当重平衡开始时,第一个给协调器发JoinGroup请求的就会成为leader
分区消费策略选择
每个给协调器发送JoinGroup消息的消费者都会在其中附带自己支持的分区消费策略,协调器在收集后会给消费者leader,并由leaderconsumer进行选择那么具体怎么选择呢?
1.收集各个消费者所支持的所有分配策略,组成候选集candidates。 2.每个消费者从候选集candidates中找出第一个自身所支持的策略,为这个策略投上一票。 3.计算候选集中各个策略的选票数,选票数最多的策略即为当前消费组的分配策略。 如果某个消费者并不支持所选举出的分配策略,那么就会报错。
|