Title

kafka13-一致性保证

1 一致性保证

1.1 概念

  • 水位标记

    水位或水印(watermark)一词,表示位置信息,即位移(offset)。Kafka源码中使用的名字是高水位,HW(high watermark)。

  • 副本角色

    Kafka分区使用多个副本(replica)提供高可用。

  • LEO和HW

    每个分区副本对象都有两个重要的属性:LEO和HW。

    1. LEO:即日志末端位移(log end offset),记录了该副本日志中下一条消息的位移值。如果 LEO=10,那么表示该副本保存了10条消息,位移值范围是[0, 9]。另外,Leader LEO和 Follower LEO的更新是有区别的。
    2. HW:即上面提到的水位值。对于同一个副本对象而言,其HW值不会大于LEO值。小于等于 HW值的所有消息都被认为是“已备份”的(replicated)。Leader副本和Follower副本的HW更 新不同。

image-20210822215156768

上图中,HW值是7,表示位移是 0~7 的所有消息都已经处于“已提交状态”(committed),而LEO 值是14,8~13的消息就是未完全备份(fully replicated)——为什么没有14?LEO指向的是下一条消息到来时的位移。

消费者无法消费分区下Leader副本中位移大于分区HW的消息。

1.2 Follower副本何时更新LEO

Follower副本不停地向Leader副本所在的broker发送FETCH请求,一旦获取消息后写入自己的日志中进行备份。那么Follower副本的LEO是何时更新的呢?首先我必须言明,Kafka有两套Follower副本 LEO:

  1. 一套LEO保存在Follower副本所在Broker的副本管理机中;
  2. 另一套LEO保存在Leader副本所在Broker的副本管理机中。Leader副本机器上保存了所有的 follower副本的LEO。

leader分区不仅维护自己的LEO,还维护了Follow的LEO

Kafka使用前者帮助Follower副本更新其HW值;利用后者帮助Leader副本更新其HW

1.2.1 Follower副本的本地LEO何时更新

Follower副本的LEO值就是日志的LEO值,每当新写入一 条消息,LEO值就会被更新。当Follower发送FETCH请求后,Leader将数据返回给 Follower,此时Follower开始Log写数据,从而自动更新LEO值

Follower HW值不会大于Leader的HW值

1.2.2 Leader端Follower的LEO何时更新

Leader在处理 Follower FETCH请求时,一旦Leader接收到Follower发送的FETCH请求,它先从Log中读取相应的数据,给Follower返回数据前,先更新Follower的LEO

1.2.3 Leader的LEO何时更新

Leader写Log时自动更新自己的LEO值

1.3 HW更新

1.3.1 Follower副本何时更新HW

Follower更新HW发生在其更新LEO之后,一旦Follower向Log写完数据,尝试更新自己的HW值。 比较当前LEO值与FETCH响应中Leader的HW值,取两者的小者作为新的HW值。

Follower HW值不会大于Leader的HW值

1.3.2 Leader副本何时更新HW值

Leader的HW值就是分区HW值,直接影响分区数据对消费者的可见性

Leader会尝试去更新分区HW的四种情况:

  1. Follower副本成为Leader副本时:Kafka会尝试去更新分区HW。
  2. Broker崩溃导致副本被踢出ISR时:检查下分区HW值是否需要更新是有必要的。
  3. 生产者向Leader副本写消息时:因为写入消息会更新Leader的LEO,有必要检查HW值是否需要更新
  4. Leader处理Follower FETCH请求时:首先从Log读取数据,之后尝试更新分区HW值

1.4 结论:

当Kafka broker都正常工作时,分区HW值的更新时机有两个:

  1. Leader处理PRODUCE请求时
  2. Leader处理FETCH请求时。

Leader如何更新自己的HW值?

Leader broker上保存了一套Follower副本的LEO以及自己的LEO。 当尝试确定分区HW时,它会选出所有满足条件的副本,比较它们的LEO(包括Leader的LEO),并选择最 小的LEO值作为HW值。

需要满足的条件,(二选一):

  1. 处于ISR中
  2. 副本LEO落后于Leader LEO的时长不大于 replica.lag.time.max.ms 参数值(默认是10s)

如果Kafka只判断第一个条件的话,确定分区HW值时就不会考虑这些未在ISR中的副本,但这些副本已经具备了“立刻进入ISR”的资格,因此就可能出现分区HW值越过ISR中副本LEO的情况(不允许)。 因为分区HW定义就是ISR中所有副本LEO的最小值

posted @ 2021-08-22 23:39  apeGcWell  阅读(102)  评论(0)    收藏  举报