分布式 - 消息队列Kafka:Kafka 副本|AR|ISR|OSR|Leader|Follower|HW|LEO

01. Kafka 复制

1. kafka 副本的分类

Kafka经常被描述成“一个分布式、分区、可复制的提交日志服务”。复制之所以这么重要,是因为它可以在个别节点失效时仍能保证Kafka的可用性和持久性。Kafka的数据保存在主题中,每个主题被分成若干个分区,每个分区可以有多个副本。副本保存在broker上,每个broker可以保存成百上千个主题和分区的副本。副本有以下两种类型:

① 首领(leader)副本:每个分区都有一个首领副本。为了保证一致性,所有生产者请求和消费者请求都会经过这个副本。客户端可以从首领副本或跟随者副本读取数据。

② 跟随者(follower)副本:首领以外的副本都是跟随者副本。如果没有特别指定,则跟随者副本将不处理来自客户端的请求,它们的主要任务是从首领那里复制消息,保持与首领一致的状态。如果首领发生崩溃,那么其中的一个跟随者就会被提拔为新首领。

2. 副本同步

首领的另一项任务是搞清楚哪些跟随者副本的状态与自己是一致的。为了保持与首领同步,跟随者会尝试从首领那里复制消息,但它们可能会因为各种原因无法与首领保持同步。例如,网络拥塞导致复制变慢,或者broker发生崩溃并重启,都将导致所有副本的复制滞后。

为了与首领保持同步,跟随者需要向首领发送Fetch请求,这与消费者为了读取消息而发送的请求是一样的。作为响应,首领会将消息返回给跟随者。Fetch请求消息里包含了跟随者想要获取的消息的偏移量,这些偏移量总是有序的。这样,首领就可以知道一个副本是否已经获取了最近一条消息之前的所有消息。通过检查每个副本请求的最后一个偏移量,首领就可以知道每个副本的滞后程度。

如果副本没有在30秒内发送请求,或者即使发送了请求但与最新消息的间隔超过了30秒,那么它将被认为是不同步的。如果一个副本未能跟上首领,那么一旦首领发生故障,它将不能再成为新首领——毕竟,它并未拥有所有的消息。

持续发出获取最新消息请求的副本被称为同步副本。当首领发生故障时,只有同步副本才有资格被选为新首领。允许跟随者可以多久不活跃或允许跟随者在多久之后成为不同步副本是通过 replica.lag.time.max.ms 参数来配置的。这个时间直接影响首领选举期间的客户端行为和数据保留机制。

3. 首选首领

除了当前的首领,每个分区都有一个首选首领,即创建主题时选定的首领。之所以是首选的,是因为在创建分区时,分区首领在broker间的分布已经是均衡的。因此,我们希望当首选首领成为当前首领时,broker之间的负载是均衡的。在默认情况下,Kafka的auto.leader.rebalance.enable会被设置为true,它会检查首选首领是不是当前首领以及是不是同步的。如果是同步的,但不是当前首领,就会触发首领选举,让首选首领成为当前首领。

可以很容易地从分区的副本列表中找到首选首领。列表中的第一个副本一般就是首选首领,不管当前首领是哪一个副本,或者使用副本分配工具将副本重新分配给了其他broker,这一点都不会改变。需要注意的是,如果你手动重新分配了副本,那么第一个指定的副本就是首选首领。因此,要确保首选首领被分配给不同的broker,避免出现少部分包含了首领的broker负载过重,其他broker却无法为它们分担负载的情况。

02. kafka 副本信息

Kafka 为分区引入了多副本(Replica)机制,通过增加副本数量可以提升容灾能力。同一分区的不同副本中保存的是相同的消息,每个分区都有一个 leader 副本和多个 follower 副本,其中leader副本负责处理读写请求,follower副本只负责与leader副本的消息同步。副本处于不同的broker中,当leader副本出现故障时,Kafka 会自动从 follower 副本中选举一个新的 leader 副本对外提供服务。这个过程称为副本重分配。在副本重分配期间,Kafka 仍然可以正常工作,但可能会出现一些延迟。Kafka通过多副本机制实现了故障的自动转移,当Kafka集群中某个broker失效时仍然能保证服务可用。

如图,Kafka集群中有4个broker,某个主题中有3个分区,且副本因子(即副本个数)也为3,如此每个分区便有1个leader副本和2个follower副本。生产者和消费者只与leader副本进行交互,而follower副本只负责消息的同步,很多时候follower副本中的消息相对leader副本而言会有一定的滞后。

在这里插入图片描述

Kafka 的副本机制可以提供以下好处:

① 数据可靠性:即使某个副本失效,数据仍然可以从其他副本中恢复。

② 高可用性:即使某个副本失效,Kafka 仍然可以正常工作。

③ 提高读取性能:由于可以从任意一个副本中读取消息,因此可以提高读取性能。

Kafka 消费端也具备一定的容灾能力。Consumer 使用拉(Pull)模式从服务端拉取消息,并且保存消费的具体位置,当消费者宕机后恢复上线时可以根据之前保存的消费位置重新拉取需要的消息进行消费,这样就不会造成消息丢失。

03. kafka 中 ISR、AR和OSR代表什么?

Kafka是一种分布式流处理平台,其中ISR、AR和OSR是Kafka中的三个重要概念。

① ISR(In-Sync Replicas):指的是与Leader副本保持同步的副本集合。当Producer发送消息到Kafka集群时,只有ISR中的副本才会被写入消息,确保数据的可靠性和一致性。如果ISR中的某个副本无法与Leader保持同步,则该副本将被从ISR中移除,直到与Leader重新同步。

② OSR(Out-of-Sync Replicas):指的是与Leader副本失去同步的副本集合。当ISR中的某个副本无法与Leader保持同步时,该副本将被移动到OSR中,直到与Leader重新同步。

③ AR(Assigned Replicas):指的是被分配到某个Partition的副本集合。AR包括ISR和OSR。

总之,ISR是Kafka中保证数据可靠性和一致性的重要机制,而AR和OSR则是与Partition相关的副本集合。

分区中的所有副本统称为AR 。所有与leader副本保持一定程度同步的副本(包括leader副本在内)组成ISR,ISR集合是AR集合中的一个子集。消息会先发送到leader副本,然后follower副本才能从leader副本中拉取消息进行同步,同步期间内follower副本相对于leader副本而言会有一定程度的滞后。前面所说的“一定程度的同步”是指可忍受的滞后范围,这个范围可以通过参数进行配置。与leader副本同步滞后过多的副本(不包括leader副本)组成OSR,由此可见,AR=ISR+OSR。在正常情况下,所有的 follower 副本都应该与 leader 副本保持一定程度的同步,即AR=ISR,OSR集合为空。

leader副本负责维护和跟踪ISR集合中所有follower副本的滞后状态,当follower副本落后太多或失效时,leader副本会把它从ISR集合中剔除。如果OSR集合中有follower副本“追上”了leader副本,那么leader副本会把它从OSR集合转移至ISR集合。默认情况下,当leader副本发生故障时,只有在ISR集合中的副本才有资格被选举为新的leader,而在OSR集合中的副本则没有任何机会。

04. kafka 中 ISR的伸缩指什么?

ISR中的伸缩指的是ISR中副本的动态变化。当某个副本落后于leader副本时,它将被从ISR中移除,直到它再次与leader副本保持同步。当某个副本追上了leader副本,它将被重新加入ISR中。这种动态变化可以通过Kafka的副本管理机制自动完成,从而保证ISR中的副本集合始终与leader副本保持同步。

05. 什么情况下一个broker会从ISR中踢出去?

ISR(In-Sync Replicas)是Kafka中用于保证数据可靠性和高可用性的机制。ISR中的副本与Leader副本保持同步,可以保证在Leader副本宕机时,ISR中的副本可以顶替成为新的Leader副本,从而保证数据的可靠性和高可用性。

一般情况下,一个broker会从ISR中踢出去有以下几种情况:

① 副本同步延迟:如果ISR中的副本与Leader副本之间的同步延迟超过了一定的阈值,那么该副本就会被从ISR中踢出去。

② 副本故障:如果ISR中的副本发生故障,比如网络故障、硬件故障等,那么该副本也会被从ISR中踢出去。

③ 副本过期:如果ISR中的副本长时间没有与Leader副本保持同步,那么该副本也会被从ISR中踢出去。

需要注意的是,当一个broker被从ISR中踢出去时,需要及时进行故障排查和修复,以保证数据的可靠性和高可用性。

06. kafka 副本和ISR扮演什么角色?

副本(Replicas)和ISR(In-Sync Replicas)是Apache Kafka中非常重要的概念,它们扮演着以下角色:

① 副本:Kafka中的每个分区都有多个副本,每个副本都是分区数据的完整拷贝。副本的作用是提高数据的可靠性和可用性。当某个副本所在的broker宕机时,其他副本可以继续提供服务,确保数据不会丢失。

② ISR:ISR是指与leader副本保持同步的副本集合。当leader副本发生故障时,ISR中的某个副本会被选举为新的leader副本。只有在ISR中的副本才能被选举为新的leader副本,因为它们保证了数据的一致性。如果某个副本与leader副本失去同步,它将被从ISR中移除,直到与leader副本重新保持同步。

因此,副本和ISR是Kafka实现高可用性和数据一致性的重要手段。

07. kafka 副本长时间不在ISR中,意味着什么?

在Kafka中,ISR(in-sync replicas)是指与leader副本保持同步的副本集合。如果一个副本长时间不在ISR中,意味着该副本与leader副本的数据同步出现了问题,可能是由于网络故障、硬件故障或其他原因导致的。这种情况下,该副本可能会落后于其他副本,导致数据不一致。因此,Kafka会将该副本从ISR中移除,以避免数据不一致的情况发生。当该副本恢复正常后,Kafka会将其重新加入ISR中,以确保数据同步。

08. kafka follower副本如何和 leader副本同步?

Kafka中的follower副本通过与leader副本进行数据同步来保持与leader副本的一致性。follower节点与leader节点同步的过程如下:

① follower节点向leader节点发送拉取请求,请求获取最新的数据。

② leader节点接收到拉取请求后,将最新的数据发送给follower节点。

③ follower节点接收到数据后,将其写入本地日志文件,并向leader节点发送确认消息,表示已经成功接收到数据。

④ leader节点接收到确认消息后,将该消息标记为已经被follower节点接收到。

⑤ follower节点定期向leader节点发送心跳消息,以保持与leader节点的连接。

⑥ 如果follower节点在一定时间内没有向leader节点发送心跳消息,或者leader节点在一定时间内没有收到follower节点的确认消息,那么leader节点将认为该follower节点已经失效,将其从副本集合中移除。

09. kafka 如何实现主从同步?

Kafka通过副本机制来实现主从同步。每个分区都有多个副本,其中一个副本被指定为领导者(leader),其他副本被指定为追随者(follower)。领导者负责处理所有的读写请求,而追随者只是简单地复制领导者的数据。

当生产者向Kafka发送消息时,它会将消息发送到领导者副本。领导者副本将消息写入本地日志,并将消息复制到所有追随者副本。一旦所有追随者副本都确认已成功复制消息,领导者副本将向生产者发送确认消息。

当消费者从Kafka读取消息时,它会从领导者副本读取数据。如果领导者副本不可用,消费者可以从追随者副本读取数据。Kafka使用ZooKeeper来管理领导者和追随者副本之间的切换,以确保高可用性和数据一致性。

10. Kafka 控制器的选举?

Kafka的控制器其实也是一个broker,只不过除了提供一般的broker功能之外,它还负责分区的首领选举。

① 控制器的选举是通过ZooKeeper实现的,只有一个broker可以成为控制器,其他broker会监听控制器节点的变化,一旦控制器节点发生变化,其他broker就会重新选举控制器。

集群中第一个启动的broker会通过在ZooKeeper中创建一个名为/controller的临时节点让自己成为控制器。其他broker在启动时也会尝试创建这个节点,但它们会收到“节点已存在”异常,并“意识”到控制器节点已存在,也就是说集群中已经有一个控制器了。其他broker会在控制器节点上创建ZooKeeper watch,这样就可以收到这个节点的变更通知了。我们通过这种方式来确保集群中只有一个控制器。

② 如果控制器被关闭或者与ZooKeeper断开连接,那么这个临时节点就会消失。控制器使用的ZooKeeper客户端没有在zookeeper.session.timeout.ms 指定的时间内向ZooKeeper发送心跳是导致连接断开的原因之一。当临时节点消失时,集群中的其他broker将收到控制器节点已消失的通知,并尝试让自己成为新的控制器。第一个在ZooKeeper中成功创建控制器节点的broker会成为新的控制器,其他节点则会收到“节点已存在”异常,并会在新的控制器节点上再次创建ZooKeeper watch。

③ 每个新选出的控制器都会通过ZooKeeper条件递增操作获得一个数值更大的epoch。其他broker也会知道当前控制器的epoch,如果收到由控制器发出的包含较小epoch的消息,就会忽略它们。这一点很重要,因为控制器会因长时间垃圾回收停顿与ZooKeeper断开连接——在停顿期间,新控制器将被选举出来。当旧控制器在停顿之后恢复时,它并不知道已经选出了新的控制器,并会继续发送消息——在这种情况下,旧控制器会被认为是一个“僵尸控制器”。消息里的epoch可以用来忽略来自旧控制器的消息,这是防御“僵尸”的一种方式。

11. Kafka 控制器负责分区的首领选举

控制器必须先从ZooKeeper加载最新的副本集状态,然后才能开始管理集群元数据和执行首领选举。

当控制器发现有一个broker离开了集群时,原先首领位于这个broker上的所有分区需要一个新首领。它将遍历所有需要新首领的分区,并决定应该将哪个分区作为新首领(可能就是副本集中的下一个副本)。然后,它会将更新后的状态持久化到ZooKeeper中,再向所有包含这些分区副本的broker发送一个LeaderAndISR请求,请求中包含了新首领和跟随者的信息。每一个新首领都知道自己要开始处理来自生产者和消费者的请求,而跟随者也知道它们要开始从新首领那里复制消息。集群中的每一个broker都有一个MetadataCache,其中包含了一个保存所有broker和副本信息的map。控制器通过UpdateMetadata请求向所有broker发送有关首领变更的信息,broker会在收到请求后更新缓存。在启动broker副本时也会有类似的过程——主要的区别是broker所有的分区副本都是跟随者,并且需要在自己有资格被选为首领之前与首领保持同步。

总的来说,Kafka会使用ZooKeeper的临时节点来选举控制器,并会在broker加入或退出集群时通知控制器。控制器负责在broker加入或退出集群时进行首领选举。控制器会使用epoch来避免“脑裂”。所谓的“脑裂”,就是指两个broker同时认为自己是集群当前的控制器。

12. kafka有哪些地方需要选举,这些地方的选举策略有哪些?

① Controller选举

Controller是Kafka集群中的一个节点,负责管理集群的元数据信息,包括Broker的上下线、Partition的分配等。当当前的Controller节点失效时,需要选举一个新的Controller节点来接管其职责。

Controller选举的策略是通过Zookeeper实现的,每个Kafka Broker都会在Zookeeper上创建一个临时节点,节点的路径为/brokers/ids/[broker-id],其中broker-id为Broker的唯一标识。当一个Broker想要成为Controller时,它会在Zookeeper上创建一个临时节点/brokers/controller_epoch,节点的值为当前的epoch值,然后尝试获取/brokers/controller节点的锁。如果获取锁成功,则该Broker成为新的Controller节点;否则,它会监听/brokers/controller节点的变化,等待锁的释放。

② Partition Leader选举

每个Partition在Kafka集群中都有一个Leader节点,负责处理该Partition的读写请求。当当前的Leader节点失效时,需要选举一个新的Leader节点来接管其职责。

Partition Leader选举的策略是通过副本之间的协作实现的。每个Partition都有多个副本,其中一个副本为Leader,其他副本为Follower。当Leader节点失效时,Follower节点会发起一次选举,选举出一个新的Leader节点。

具体的选举过程如下:

  • Follower节点向所有其他副本发送一个Leader选举请求,请求中包含该Partition的最后一条消息的offset值。
  • 如果其他副本中有一个副本的最后一条消息的offset值大于等于该Follower节点的offset值,则该副本成为新的Leader节点。
  • 如果没有副本的offset值大于等于该Follower节点的offset值,则该Follower节点等待一段时间后重新发起选举请求。

需要注意的是,为了避免脑裂(split-brain)的情况发生,Kafka要求每个Partition至少有一个副本处于活跃状态,否则该Partition将无法使用。因此,在进行Leader选举时,只有那些处于活跃状态的副本才能参与选举。

13. kafka Partition Leader选举

Kafka是一个分布式的消息系统,它将消息分成多个分区(Partition)并存储在多个Broker上。每个分区都有一个Leader和多个Follower,Leader负责处理读写请求,Follower则从Leader同步数据。

当一个Broker宕机或者网络故障导致Leader无法正常工作时,Kafka需要进行Partition Leader选举,选出一个新的Leader来处理读写请求。选举的过程如下:

① 每个Broker都会定期向Zookeeper注册自己的Broker信息,并创建一个临时节点。这个节点的路径是/brokers/ids/[broker-id],节点的值是一个JSON格式的字符串,包含了Broker的IP地址、端口号等信息。

② 当一个Broker宕机或者网络故障导致Leader无法正常工作时,Zookeeper会检测到这个Broker的临时节点被删除,然后通知其他Broker。

③ 其他Broker会检查所有的Partition,如果某个Partition的Leader是宕机的Broker,那么它会尝试成为新的Leader。它会向Zookeeper创建一个临时节点/brokers/topics/[topic]/[partition]/[broker-id],表示它想要成为这个Partition的Leader。

④ 如果多个Broker都尝试成为Leader,那么Zookeeper会根据节点创建时间的先后顺序来选举Leader。创建时间最早的节点会成为新的Leader。

⑤ 选举完成后,新的Leader会向Zookeeper更新Partition的元数据,其他Broker会从Zookeeper获取最新的元数据,并更新自己的缓存。

需要注意的是,Kafka的Partition Leader选举是异步的,也就是说,选举完成后,可能会有一段时间内某些消息无法被正常处理。因此,Kafka的高可用性需要依赖于多个副本(Replica)的存在,以保证即使某个Broker宕机,也能够保证消息的可靠性和可用性。

14. kafka Partition Leader选举流程

Kafka 集群中有一个 broker 的 Controller 会被选举为 Controller Leader,负责管理集群 broker 的上下线,所有 topic 的分区副本分配和 Leader 选举等工作。Controller 的信息同步工作是依赖于 Zookeeper 的。

选举流程:

① kafka每启动一个节点就会在zookeeper中注册一个节点信息,每一个broker节点都有对应的Controller,他们会争先抢占Controller的注册,谁先注册谁会被选举为 Controller Leader。

② 选举出来的 Controller 会监听 brokers 节点变化,决定 Leader 的选举,将节点信息上传到 zookeeper,其他Contorller 就会从 zookeeper 同步相关信息。

③ 假设 Broker1 中 Leader 挂了,Controller 就会监听到节点变化,然后获取到 ISR,选举新的 Leader(在 ISR 中存活为前提,按照 AR 中排在前面的优先),更新 Leader 及 ISR。
在这里插入图片描述

利用3台服务器(brokerId=0,1,2)集群来验证以上整个流程 :

① 创建一个新的 topic,3 个分区,3 个副本:

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --create --partitions 3 --replication-factor 3  --topic test1

② 查看 Leader 分布情况:

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1,0,2
Topic: test1    Partition: 1    Leader: 2       Replicas: 2,1,0 Isr: 2,1,0
Topic: test1    Partition: 2    Leader: 0       Replicas: 0,2,1 Isr: 0,2,1

③ 停止掉 brokerId=0 的 kafka 进程,并查看 Leader 分区情况:

假如 brokerId=0 的 kafka 进程挂掉了,那么Partition为2 的Leader 就会重新选举,选举的规则为:在 ISR 中存活为前提,按照AR中排在前面的优先,即新的Leader将是2。

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1,0,2
Topic: test1    Partition: 1    Leader: 2       Replicas: 2,1,0 Isr: 2,1,0
Topic: test1    Partition: 2    Leader: 0       Replicas: 0,2,1 Isr: 0,2,1

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1,2
Topic: test1    Partition: 1    Leader: 2       Replicas: 2,1,0 Isr: 2,1
Topic: test1    Partition: 2    Leader: 2       Replicas: 0,2,1 Isr: 2,1

④ 停止掉 brokerId=2 的 kafka 进程,并查看 Leader 分区情况:

假如 brokerId=2 的 kafka 进程挂掉了,那么 Partition1和 Partition2 的Leader 就会重新选举,选举的规则为:在 ISR 中存活为前提,按照AR中排在前面的优先,即Partition1 和 Partition2 新的Leader都将是1。

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1,2
Topic: test1    Partition: 1    Leader: 2       Replicas: 2,1,0 Isr: 2,1
Topic: test1    Partition: 2    Leader: 2       Replicas: 0,2,1 Isr: 2,1

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1
Topic: test1    Partition: 1    Leader: 1       Replicas: 2,1,0 Isr: 1
Topic: test1    Partition: 2    Leader: 1       Replicas: 0,2,1 Isr: 1

⑤ 启动 brokerId=0 的 kafka 进程,并查看 Leader 分区情况:

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1
Topic: test1    Partition: 1    Leader: 1       Replicas: 2,1,0 Isr: 1
Topic: test1    Partition: 2    Leader: 1       Replicas: 0,2,1 Isr: 1

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1,0
Topic: test1    Partition: 1    Leader: 1       Replicas: 2,1,0 Isr: 1,0
Topic: test1    Partition: 2    Leader: 1       Replicas: 0,2,1 Isr: 1,0

⑥ 启动 brokerId=2 的 kafka 进程,并查看 Leader 分区情况:

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1,0,2
Topic: test1    Partition: 1    Leader: 1       Replicas: 2,1,0 Isr: 1,0,2
Topic: test1    Partition: 2    Leader: 1       Replicas: 0,2,1 Isr: 1,0,2

⑦ 停止掉 brokerId=1 的 kafka 进程,并查看 Leader 分区情况:

假如 brokerId=1 的 kafka 进程挂掉了,那么 Partition0、Partition1和 Partition2 的Leader 就会重新选举,选举的规则为:在 ISR 中存活为前提,按照AR中排在前面的优先,即 Partition0 的Leader将为0,Partition1 的Leader将为2, Partition2 的Leader将是0。

[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1,0,2
Topic: test1    Partition: 1    Leader: 1       Replicas: 2,1,0 Isr: 1,0,2
Topic: test1    Partition: 2    Leader: 1       Replicas: 0,2,1 Isr: 1,0,2
        
[root@localhost kafka-01]# bin/kafka-topics.sh --zookeeper localhost:2182 --describe --topic test1
Topic:test1     PartitionCount:3        ReplicationFactor:3     Configs:
Topic: test1    Partition: 0    Leader: 0       Replicas: 1,0,2 Isr: 0,2
Topic: test1    Partition: 1    Leader: 2       Replicas: 2,1,0 Isr: 0,2
Topic: test1    Partition: 2    Leader: 0       Replicas: 0,2,1 Isr: 0,2

可以看出选举是按照AR中的顺序轮询选举的,而不是ISR中的顺序。

15. kafka HW和LEO代表什么?

HW是High Watermark的缩写,俗称高水位,它标识了一个特定的消息偏移量(offset),消费者只能拉取到这个offset之前的消息。

如图 ,它代表一个日志文件,这个日志文件中有 9 条消息,第一条消息的 offset 为0,最后一条消息的offset为8,offset为9的消息用虚线框表示,代表下一条待写入的消息。日志文件的HW为6,表示消费者只能拉取到offset在0至5之间的消息,而offset为6的消息对消费者而言是不可见的。

在这里插入图片描述

LEO是Log End Offset的缩写,它标识当前日志文件中下一条待写入消息的offset,图中offset为9的位置即为当前日志文件的LEO,LEO的大小相当于当前日志分区中最后一条消息的offset值加1。分区ISR集合中的每个副本都会维护自身的LEO,而ISR集合中最小的LEO即为分区的HW,对消费者而言只能消费HW之前的消息。

注意要点:很多资料中误将图中的offset为5的位置看作HW,而把offset为8的位置看作LEO,这显然是不对的。

16. 如何理解ISR集合与HW和LEO的关系?

① 假设某个分区的ISR集合中有3个副本,即一个leader副本和2个follower副本,此时分区的LEO和HW都为3。消息3和消息4从生产者发出之后会被先存入leader副本:

在这里插入图片描述

② 在消息写入leader副本之后,follower副本会发送拉取请求来拉取消息3和消息4以进行消息同步:

在这里插入图片描述

③ 在同步过程中,不同的 follower 副本的同步效率也不尽相同,在某一时刻follower1完全跟上了leader副本而follower2只同步了消息3,如此leader副本的LEO为5,follower1的LEO为5,follower2的LEO为4,那么当前分区的HW取最小值4,此时消费者可以消费到offset为0至3之间的消息。

在这里插入图片描述

④ 所有的副本都成功写入了消息3和消息4,整个分区的HW和LEO都变为5,因此消费者可以消费到offset为4的消息了。

在这里插入图片描述

Kafka 的复制机制既不是完全的同步复制,也不是单纯的异步复制。事实上,同步复制要求所有能工作的 follower 副本都复制完,这条消息才会被确认为已成功提交,这种复制方式极大地影响了性能。而在异步复制方式下,follower副本异步地从leader副本中复制数据,数据只要被leader副本写入就被认为已经成功提交。在这种情况下,如果follower副本都还没有复制完而落后于leader副本,突然leader副本宕机,则会造成数据丢失。Kafka使用的这种ISR的方式则有效地权衡了数据可靠性和性能之间的关系。

猜你喜欢

转载自blog.csdn.net/qq_42764468/article/details/131404837