控制器组件(Controller),是 Apache Kafka 的外围组件。它的次要作用是在 Apache ZooKeeper 的帮忙下治理和协调整个 Kafka 集群。集群中任意一台 Broker 都能充当控制器的角色,然而,在运行过程中,只能有一个 Broker 成为控制器,行使其治理和协调的职责。接下来,咱们将探讨Controller原理和外部运行机制。通过本文你能够理解到:
- 什么是Controller Broker
- Controller Broker是怎么被选举的
- Controller Broker次要作用是什么
- Kafka是如何解决脑裂的
在分布式系统中,通常须要有一个协调者,该协调者会在分布式系统产生异样时施展非凡的作用。在Kafka中该协调者称之为控制器(Controller),其实该控制器并没有什么非凡之处,它自身也是一个一般的Broker,只不过须要负责一些额定的工作(追踪集群中的其余Broker,并在适合的时候解决新退出的和失败的Broker节点、Rebalance分区、调配新的leader分区等)。值得注意的是:Kafka集群中始终只有一个Controller Broker。
Controller Broker是如何被选出来的
上一大节解释了什么是Controller Broker,并且每台 Broker 都有充当控制器的可能性。那么,控制器是如何被选出来的呢?当集群启动后,Kafka 怎么确认控制器位于哪台 Broker 呢?
实际上,Broker 在启动时,会尝试去 ZooKeeper 中创立 /controller 节点。Kafka 以后选举控制器的规定是:第一个胜利创立 /controller 节点的 Broker 会被指定为控制器。
Controller Broker的具体作用是什么
Controller Broker的主要职责有很多,次要是一些治理行为,次要包含以下几个方面:
- 创立、删除主题,减少分区并调配leader分区
- 集群Broker治理(新增 Broker、Broker 被动敞开、Broker 故障)
- preferred leader选举
- 分区重调配
解决集群中下线的Broker
当某个Broker节点因为故障来到Kafka群集时,则存在于该Broker的leader分区将不可用(因为客户端仅对leader分区进行读写操作)。为了最大水平地缩小停机工夫,须要疾速找到代替的leader分区。
Controller Broker能够对失败的Broker做出响应,Controller Broker能够从Zookeeper监听(zookeeper watch)中获取告诉信息,ZooKeeper 赋予客户端监控 znode 变更的能力,即所谓的 Watch 告诉性能。一旦 znode 节点被创立、删除,子节点数量发生变化,抑或是 znode 所存的数据自身变更,ZooKeeper 会通过节点变更监听器 (ChangeHandler) 的形式显式告诉客户端。
每个 Broker 启动后,会在zookeeper的 /Brokers/ids 下创立一个长期 znode。当 Broker 宕机或被动敞开后,该 Broker 与 ZooKeeper 的会话完结,这个 znode 会被主动删除。同理,ZooKeeper 的 Watch 机制将这一变更推送给控制器,这样控制器就能晓得有 Broker 敞开或宕机了,从而进行后续的协调操作。
Controller将收到告诉并对此采取行动,决定哪些Broker上的分区成为leader分区,而后,它会告诉每个相干的Broker,要么将Broker上的主题分区变成leader,要么通过LeaderAndIsr
申请从新的leader分区中复制数据。
解决新退出到集群中的Broker
通过将Leader分区正本平均地散布在集群的不同Broker上,能够保障集群的负载平衡。在Broker产生故障时,某些Broker上的分区正本会被选举为leader,会造成一个Broker上存在多个leader分区正本的状况,因为客户端只与leader分区正本交互,所以这会给Broker减少额定的累赘,并侵害集群的性能和运行状况。因而,尽快恢复均衡对集群的衰弱运行是无益的。
Kafka认为leader分区正本最后的调配(每个节点都处于沉闷状态)是平衡的。这些被最后选中的分区正本就是所谓的首选领导者(preferred leaders)。因为Kafka还反对机架感知的leader选举(rack-aware leader election) ,即尝试将leader分区和follower分区搁置在不同的机架上,以减少对机架故障的容错能力。因而,leader分区正本的存在地位会对集群的可靠性产生影响。
默认状况下auto.leader.rebalance.enabled为true,示意容许 Kafka 定期地对一些 Topic 分区进行
Leader 重选举。大部分状况下,Broker的失败很短暂,这意味着Broker通常会在短时间内复原。所以当节点来到群集时,与其相关联的元数据并不会被立刻删除。
当Controller留神到Broker已退出集群时,它将应用Broker ID来查看该Broker上是否存在分区,如果存在,则Controller告诉新退出的Broker和现有的Broker,新的Broker下面的follower分区再次开始复制现有leader分区的音讯。为了保障负载平衡,Controller会将新退出的Broker上的follower分区选举为leader分区。
留神:下面提到的选Leader分区,严格意义上是换Leader分区,为了达到负载平衡,可能会造成原来失常的Leader分区被强行变为follower分区。换一次 Leader 代价是很高的,本来向 Leader分区A(原Leader分区) 发送申请的所有客户端都要切换成向 B (新的Leader分区)发送申请,倡议你在生产环境中把这个参数设置成 false。
同步正本(in-sync replica ,ISR)列表
ISR中的正本都是与Leader进行同步的正本,所以不在该列表的follower会被认为与Leader是不同步的. 那么,ISR中存在是什么正本呢?首先能够明确的是:Leader正本总是存在于ISR中。 而follower正本是否在ISR中,取决于该follower正本是否与Leader正本放弃了“同步”。
始终保障领有足够数量的同步正本是十分重要的。要将follower晋升为Leader,它必须存在于同步正本列表中。每个分区都有一个同步正本列表,该列表由Leader分区和Controller进行更新。
抉择一个同步正本列表中的分区作为leader 分区的过程称为clean leader election。留神,这里要与在非同步正本当选一个分区作为leader分区的过程辨别开,在非同步正本当选一个分区作为leader的过程称之为unclean leader election。因为ISR是动静调整的,所以会存在ISR列表为空的状况,通常来说,非同步正本落后 Leader 太多,因而,如果抉择这些正本作为新 Leader,就可能呈现数据的失落。毕竟,这些正本中保留的音讯远远落后于老 Leader 中的音讯。在 Kafka 中,选举这种正本的过程能够通过Broker 端参数 unclean.leader.election.enable 管制是否容许 Unclean 领导者选举。开启 Unclean 领导者选举可能会造成数据失落,但益处是,它使得分区 Leader 正本始终存在,不至于进行对外提供服务,因而晋升了高可用性。反之,禁止 Unclean Leader 选举的益处在于保护了数据的一致性,防止了音讯失落,但就义了高可用性。分布式系统的CAP实践说的就是这种状况。
可怜的是,unclean leader election的选举过程仍可能会造成数据的不统一,因为同步正本并不是齐全同步的。因为复制是异步实现的,因而无奈保障follower能够获取最新消息。比方Leader分区的最初一条音讯的offset是100,此时正本的offset可能不是100,这受到两个参数的影响:
- replica.lag.time.max.ms:同步正本滞后与leader正本的工夫
- zookeeper.session.timeout.ms:与zookeeper会话超时工夫
脑裂
如果controller Broker 挂掉了,Kafka集群必须找到能够代替的controller,集群将不能失常运行。这外面存在一个问题,很难确定Broker是挂掉了,还是仅仅只是短暂性的故障。然而,集群为了失常运行,必须选出新的controller。如果之前被取代的controller又失常了,他并不知道本人曾经被取代了,那么此时集群中会呈现两台controller。
其实这种状况是很容易产生。比方,某个controller因为GC而被认为曾经挂掉,并抉择了一个新的controller。在GC的状况下,在最后的controller眼中,并没有扭转任何货色,该Broker甚至不晓得它曾经暂停了。因而,它将持续充当以后controller,这是分布式系统中的常见状况,称为脑裂。
如果,处于沉闷状态的controller进入了长时间的GC暂停。它的ZooKeeper会话过期了,之前注册的/controller
节点被删除。集群中其余Broker会收到zookeeper的这一告诉。
因为集群中必须存在一个controller Broker,所以当初每个Broker都试图尝试成为新的controller。假如Broker 2速度比拟快,成为了最新的controller Broker。此时,每个Broker会收到Broker2成为新的controller的告诉,因为Broker3正在进行”stop the world”的GC,可能不会收到Broker2成为最新的controller的告诉。
等到Broker3的GC实现之后,仍会认为本人是集群的controller,在Broker3的眼中如同什么都没有产生一样。
当初,集群中呈现了两个controller,它们可能一起收回具备抵触的命令,就会呈现脑裂的景象。如果对这种状况不加以解决,可能会导致重大的不统一。所以须要一种办法来辨别谁是集群以后最新的Controller。
Kafka是通过应用epoch number(纪元编号,也称为隔离令牌)来实现的。epoch number只是枯燥递增的数字,第一次选出Controller时,epoch number值为1,如果再次选出新的Controller,则epoch number将为2,顺次枯燥递增。
每个新选出的controller通过Zookeeper 的条件递增操作取得一个全新的、数值更大的epoch number 。其余Broker 在晓得以后epoch number 后,如果收到由controller收回的蕴含较旧(较小)epoch number的音讯,就会疏忽它们,即Broker依据最大的epoch number来辨别以后最新的controller。
上图,Broker3向Broker1收回命令:让Broker1上的某个分区正本成为leader,该音讯的epoch number值为1。于此同时,Broker2也向Broker1发送了雷同的命令,不同的是,该音讯的epoch number值为2,此时Broker1只服从Broker2的命令(因为其epoch number较大),会疏忽Broker3的命令,从而防止脑裂的产生。
总结
本文次要解说了什么是Kafka Controller,它其实就是一个一般的Broker,除了须要负责一些额定的工作之外,其角色与其余的Broker根本一样。另外还介绍了Kafka Controller的主要职责,并对其中的一些职责进行了具体解释,最初还阐明了kafka是如何防止脑裂的。
公众号『大数据技术与数仓』,回复『材料』支付大数据资料包
发表回复