初识Kafka术语(二)

之前学习了一些基本的术语,看了文档和书籍以后,发现还有一些术语需要掌握。

副本

分区中的所有副本称为AR(Assigned Replicas)。所有与Leader副本保持一定程度同步的部分(包括Leader副本在内)组成ISR(In-Sync Replicas),ISR集合是AR集合中的一个子集。消息会先发送到Leader副本,然后Follower副本从Leader副本中拉取消息进行同步,同步期间内Follower副本相对于Leader副本会有一定程度的滞后。

所说的一定程度同步是指可忍受的范围,Kafka判断Follower是否与Leader同步的标准就是Broker端参数replica.lag.time.max.ms的参数值。这个参数的含义是Follower副本能够落后Leader副本的最长时间间隔,当前默认值是10秒。这就是说,只要一个Follower副本落后Leader副本的时间不连续超过10秒,那么Kafka就认为该Follower副本与Leader是同步的,即使此时Follower副本中保存的消息明显少于Leader副本中的消息。

与Leader副本同步滞后过多的副本组成OSR(Out-of-Sync Replicas),即AR=ISR+OSR。正常情况下,所有的Follower副本都应该与Leader副本保持一定程度的同步,即AR=ISR。Leader副本负责维护和跟踪ISR集合中所有Follower副本的滞后状态,当Follower副本落后太多或失效时,Leader副本会把它从ISR集合中剔除。倘若OSR集合中有Follower追上Leader副本的进度,会从重新加回ISR集合。也就是说,ISR是一个动态调整的集合,而非静态不变的。

高水位

高水位(High Watermark),在Kafka中,高水位的作用主要有2个:

  • 定义消息可见性,即用来标识分区下的哪些消息是可以被消费者消费的;
  • 帮助Kafka完成副本同步。

如上图,在分区高水位以下的消息被认为是已提交消息,反之就是未提交消息。消费者只能消费已提交消息,即图中位移小于5的所有消息。

LEO(Log End Offset, 日志末端位移), 它表示副本写入下一条消息的位移值。注意,数字9所在的方框是虚线,说明这个副本当前只有9条消息,位移值是从0到8,下一条新消息的位移是9。显然,介于高水位和LEO之间的消息就属于未提交消息。这也从侧面告诉了我们一个重要的事实,那就是:同一个副本对象,其高水位值不会大于LEO值。高水位和LEO是副本对象的两个重要属性。Kafka所有副本都有对应的高水位和LEO 值,而不仅仅是Leader副本。只不过Leader副本比较特殊,Kafka使用Leader副本的高水位来定义所在分区的高水位。换句话说,分区的高水位就是其Leader副本的高水位。

Leader Epoch

Follower副本的高水位更新需要一轮额外的拉取请求才能实现。也就是说,Leader副本高水位更新和Follower副本高水位更新在时间上是存在错配的。这种错配是很多“数据丢失”或“数据不一致”问题的根源。基于此,社区在0.11版本正式引入了Leader Epoch概念,来规避因高水位更新错配导致的各种不一致问题。

Leader Epoch由两部分数据组成:

  • Epoch。一个单调增加的版本号。每当副本领导权发生变更时,都会增加该版本号。小版本号的Leader被认为是过期Leader,不能再行使 Leader权力。
  • 起始位移(Start Offset)。Leader副本在该Epoch值上写入的首条消息的位移。

Kafka Broker会在内存中为每个分区都缓存Leader Epoch数据,同时它还会定期地将这些信息持久化到一个checkpoint文件中。当Leader副本写入消息到磁盘时,Broker会尝试更新这部分缓存。如果该Leader是首次写入消息,那么Broker会向缓存中增加一个Leader Epoch条目,否则就不做更新。这样,每次有Leader变更时,新的Leader副本会查询这部分缓存,取出对应的Leader Epoch的起始位移,以避免数据丢失和不一致的情况。

参考

1、Kafka核心技术与实战
2、《深入理解Kafka核心设计与实践原理》

0%