Kafka中的选举机制

序言:

Kafka作为一个分布式消息中间件(存储消息).既然是一个分布式存储系统(message是分区进行存储),那么肯定需要考虑到数据一致性算法的实现。对于现在较多的开源分布式系统基本会采用两种思路:第一基于paxos算法(衍生出来其它算法例如Fast Paxos,zookeeper的ZAB原子广播协议),第二种基于leader与follower多副本机制(对于数据的写入,同一由leader进行管理写入,follower基本与leader进行同步,例如Raft算法-Nacos实现,Bully霸道选举算法-Ealsticsearch中)。而Kafka作为一个分布式系统,Kafka集群中的选举大致可以分为二类:控制器的选举、分区leader的选举。

1:控制器选举

在Kafka集群中有多个broker,那么就有一个broker会被选举为控制器(Kafka Controller),它的作用负责管理整个集群中所有分区和副本的状态。比如当某个分区的leader副本出现故障时,由控制器负责为该分区选举新的leader副本。再比如当检测到某个分区的ISR集合发生变化时,由控制器负责通知所有broker更新其元数据信息。控制器的选举是由Zookeeper(协调框架)的节点的唯一性来做到的,在kafka中多个broker启动后会在Zookeeper创建/controller这个临时(EPHEMERAL)节点,哪个broker创建成功,那么它就成为了控制器,其它竞争失败的broker会进行watch注册。

2:分区leader的选举

Kafka是一个多分区,多副本的消息服务,那么每个分区的多副本由一个leader与多个follower构成(分区中 的所有副本统称为 AR ( Assigned Replicas ),而leader负责进行数据读写,并且管理着整个follower中存储的数据状态,例如lastOffset,而follower定时的会同步(这里的同步其实指的是异步同步,而同步指的是producer的ack>1ack=-1即leader写入完成,并且其它副本也写入完成才代表该消息才被确定成功提交,这种ack可选机制,是kafka提供我们*对数据可靠性和性能之间进行平衡,也针对不同应用场景)leader中的offset(同步期间内follower 副本相对于 leader 副本会有一定程度滞后,这个滞后的范围可以通过参数进行配置 ),一旦leader检测某个follower落后leader太多,leader就将该follower剔除ISR列表(ISR-In-Sync-Replicas该列表由leader副本与和leader中offset相差不多的follwer构成),这些被剔除的副本构建了一个OR(offline-Replicas)列表。而AR=ISR+OR,若某一时刻该分区leader挂掉了(z那么该分区在leader未被重新选举期间都是不可用的),Broker控制器就会对该分区进行重新选举案leader副本,其中leader的诞生只能从ISR列表中产生(这不是绝对的,如果我们设置unclean.leader.election.enable=false,是否可以从非 ISR 集合中选举 leader 副本,不过这样做的结果就是产生数据丢失)。

Kafka中的选举机制
Kafka中Partition信息类

 分区leader选举过程:

对于kafka集群中对于任意的topic的分区以及副本leader的设定,都需要考虑到集群整体的负载能力的平衡性,会尽量分配每一个partition的副本leader在不同的broker中,这样会避免多个leader在同一个broker,导致集群中的broker负载不平衡。kafka引入了优先副本的概念,优先副本的意思在AR集合列表中的第一个副本,在理想状态下该副本就是该分区的leader副本。如下所示:例如kafka集群由3台broker组成,创建了一个名为topic-partitions的topic,设置partition为3,副本数为3,partition0中AR列表为 [1,2,0],那么分区0的优先副本为1,分区1优先副本为2,分区3优先副本为0,正好每一个leader都在不同的broker。

Kafka中的选举机制

当我们把broker 2进行重启,这个时候该topic 详细情况如下所示:

Kafka中的选举机制

发现分区中副本的leader分布发生了变化 partition1中leader所在brokerId由2->0,依据来源AR列表中(当然0副本若不在ISR列表中,那么即使0的优先级比1高,仍然是由1当选)。这样就打破了集群的负载平衡性,kafka针对这种情况提供了自动leader自动平衡策略(由broker中server.properties中auto.leader.rebalance.enable=true设置,默认为true,该策略会根据集群状态重新进行leader选举),该策略可以保证避免因集群中某些服务器挂掉导致副本leader集中到某些节点中。但这也带来了一定问题如果在kafka在关键时期执行关键任务的关卡上执行优先副本的自动选举操作,势必会有业务阻塞、频繁超时之类的风险。可以针对此类相关的埋 点指标设置相应的告警机制(例如邮件,短信,企业微信等通知方式),在合适的时机由运维进行手动执行的方式进行分区平衡,具体可通过kafka-perferred-replicaelection.sh脚本(关于该脚本可自行百度)提供了对分区 leader 副本进行重新平衡的功能。