Kafka 对于 Producer 生产的消息怎么保证可靠性?简单说就是每个 Partation 都分配给副本,做数据同步,保证数据不丢失。
副本同步策略(ISR):
kafka 不是完全同步,也不是完全异步,是一种 ISR 机制,先来了解下完全同步的优势劣势
完全同步的优点:同样为了容忍 N 台节点的故障,过半机制需要 2N+1 个副本,而全部同步方案只需要 N+1 个副本,
而 Kafka 的每个分区都有大量的数据,过半机制方案会造成大量数据的冗余。
完全同步缺陷:假设就有这么一个 follower 延迟太高或者某种故障的情况出现,导致迟迟不能与 leader 进行同步。
等:就会造成数据延迟及其严重。
不等:就说不上完全同步。
所以就有了 Kafka 所谓的完全同步策略 ISR。那么什么叫做 ISR 呢?咱们先了解几个概念:
AR(Assigned Repllicas)一个 partition 的所有副本(就是 replica,不区分 leader 或 follower)
ISR(In-Sync Replicas)能够和 leader 保持同步的 follower + leader 本身 组成的集合。
OSR(Out-Sync Relipcas)不能和 leader 保持同步的 follower 集合
公式:AR = ISR + OSR
由此可以知道Kafka 只保证对 ISR 集合中的所有副本保证完全同步。ISR 就是 Kafka 一定会保证 leader 接收到的消息完全同步给 ISR 中的所有副本。
而最坏的情况下,ISR 中只剩 leader 自己。
基于此,上述完全同步会出现的缺陷也就不再是问题了,因为 ISR 的机制就保证了,处于 ISR 内部的 follower 都是可以和 leader 进行同步的,一旦出现故障或延迟,就会被踢出 ISR。
ISR 的核心就是:动态调整
总结:Kafka 采用的就是一种完全同步的方案,而 ISR 是基于完全同步的一种优化机制。
Follower 的作用:读写都是由 leader 处理,follower 只是作备份功能,不对外提供服务。
什么情况 ISR 中的 replica 会被踢出 ISR?
Kafka 配置:一个衡量 leader 和 follower 之间差距的标准
# 默认10000 即 10秒 replica.lag.time.max.ms # 允许 follower 副本落后 leader 副本的消息数量,超过这个数量后,follower 会被踢出 ISR replica.lag.max.messagesreplica.lag.max.messages
一个是基于时间间隔,一个是基于消息条数,0.9.0.0 版本之后,移除了 replica.lag.max.messages 配置。
因为 producer 是可以批量发送消息的,很容易超过 replica.lag.max.messages,那么被踢出 ISR 的 follower 就是受了无妄之灾。为什么这么说?因为都是没问题的,既没有出故障也没高延迟,因为超过 replica.lag.max.messages,凭什么被踢?
那么 replica.lag.max.messages 调大呢?调多大?太大了是否会有漏网之鱼,造成数据丢失风险?这就是 replica.lag.max.messages 的设计缺陷。
replica.lag.time.max.ms
误区注意:只要在 replica.lag.time.max.ms 时间内 follower 有同步消息,即认为该 follower 处于 ISR 中。
千万不要这么认为,这里还涉及一个
速率问题(理解为蓄水池一个放水一个注水的问题)。如果 leader 副本的消息流入速度大于 follower 副本的拉取速度时,你 follower 就是实时同步有什么用?
典型的出工不出力,消息只会越差越多,这种 follower 肯定是要被踢出 ISR。正确理解:当 Follower 副本将 Leader 副本的 LEO 之前的日志全部同步时,则认为该 Follower 副本已经追赶上 Leader 副本, 此时更新该副本的 lastCaughtUpTimeMs 标识。 Kafka 的副本管理器(ReplicaManager)启动时会启动一个副本过期检测的定时任务,会定时检查当前时间与副本的 lastCaughtUpTimeMs 差值是否大于参数
replica.lag.time.max.ms指定的值。 所以replica.lag.time.max.ms的正确理解是:Follower 在过去的replica.lag.time.max.ms时间内,已经追赶上 leader 一次了。
Follower 会出现的问题
两个方面,一个是Kafka自身的问题,另一个是外部原因
Kafka 源码注释中说明了一般有两种情况会导致副本失效:
1、follower 副本进程卡住,在一段时间内根本没有想 leader 副本发起同步请求,比如频繁的 Full GC。
2、follower 副本进程同步过慢,在一段时间内都无法追赶上 leader 副本,比如 IO 开销过大。
1、通过工具增加了副本因子,那么新增加的副本在赶上 leader 副本之前也都是处于失效状态的。
2、如果一个 follower 副本由于某些原因(比如宕机)而下线,之后又上线,在追赶上 leader 副本之前也是出于失效状态。
什么情况 OSR 中的 replica 会重新加入 ISR?
基于上述,replica 重新追上了 leader,就会回到 ISR 中。