【Kafka】图解 partition 维护 ISR 列表的底层机制是如何设计的?

993 阅读3分钟

这里不得不提 2 个重要参数:

# kafka 0.9.0 版本之前存在的参数
# 这个参数规定了 follower 如果落后 Leader 的消息数量超过了这个参数指定的数量之后,
# 就会认为 follower 是 out-of-sync,就会从 ISR 列表里移除
replica.lag.max.messages
​
# kafka 0.10.x 新增的参数
# 与 leader 上一次交互时间超过阈值就会把 follower 剔除出 ISR
replica.lag.time.max.ms

为什么新版本移除 replica.lag.max.messages 参数?

  1. 设置太大了,影响真正“落后” follower 的移除
  2. 设置的太小了,导致 follower 的频繁进出。无法给定一个合适的 replica.lag.max.messages的值,故此,新版本的Kafka移除了这个参数。

一些概念:

  • AR(Assigned Repllicas)一个 partition 的所有副本(就是 replica,不区分 leaderfollower
  • ISR(In-Sync Replicas) 能够和 Leader 保持同步的 follower + leader 本身 组成的集合。
  • OSR(Out-Sync Relipcas)不能和 Leader 保持同步的 follower 集合

这里就不得不提 Producer 的一个重要的参数:acks

  • acks=0:不需要等待服务器的确认. 这是 retries 设置无效. 响应里来自服务端的 offset 总是 -1producer只管发不管发送成功与否。延迟低,容易丢失数据。
  • acks=1:表示 leader 写入成功(但是并没有刷新到磁盘)后即向 producer 响应。延迟中等,一旦 leader 副本挂了,就会丢失数据。
  • acks=all:等待数据完成副本的复制, 等同于 -1. 假如需要保证消息不丢失, 需要使用该设置. 同时需要设置 unclean.leader.election.enabletrue, 保证当 ISR 列表为空时, 选择其他存活的副本作为新的 leader.

replica.lag.max.messages参数 举个栗子:

前提:

# 副本有 3 个,1 个 leader 和 2 个 follower
replication-factor = 3# 最小同步数为1,1个副本写入数据就认为写入成功
min.insync.replicas = 2# 这个参数规定了 follower 如果落后 Leader 的消息数量超过了这个参数指定的数量之后,
# 就会认为 follower 是 out-of-sync,就会从 ISR 列表里移除
replica.lag.max.messages = 3
  1. 初始时:LeaderFollower 均有 3 条数据,LEOOffset = 3 的位置

2022-06-1202-22-56.png 2. 进来一条数据:LeaderFollower 副本B 均成功写入新数据,Follower副本C 没有写入(因为所在机器性能突然降低),此时 LeaderLEO = 4,HW = 3

> 如果这时候,要求所有副本写入成功才算写入成功`min.insync.replicas = 3` ,那么生产者会认为还没写入成功。

2022-06-1202-32-37.png

  1. Follower 副本C 突然 fullgcfullgc 一般持续好几秒

2022-06-1202-44-05.png

  1. 进来三条数据:LeaderFollower 副本B 均成功写入新数据,LeaderLEO = 7, HW = 3

    注意:消费者只能读取小于 HW 的数据,大于 HW 的数据是读取不了的。

2022-06-1202-51-51.png

  1. 触发阈值:Follower副本C的 LEO = 3LeaderLEO = 7 差距超过 3 了,这时就会把 Follower 副本C 移除了。

    这时候,只有2个副本在,HW 也往前推进了,此时消费者可以消费全部数据了。

2022-06-1202-57-32.png

  1. Follower副本C fullgc 结束:这时,副本C 拼命同步数据,慢慢地LEO 又控制在 replica.lag.max.messages 限定的范围内,此时副本C 就会重新加回到 ISR 列表里

2022-06-1203-04-06.png

综上,简单走了一遍 ISR 维护过程。

现在想下,导致 Follower 更新跟不上的情况主要有三种:

  1. Follower 所在机器的性能比那差: 比如网络负载过高、IO 负载过高、CPU 负载过高、机器负载过高等,都有可能导致机器性能变差。
  2. Follower 所在的 Broker 进程卡顿: 常见就是 fullgc 问题
  3. 动态调节副本数量: 动态增加了 partition 的副本,就会增加新的 Follower ,此时新的 Follower 会拼命从 Leader 上同步数据,但是这个需要一段时间