Kafka对于Producer生产的消息怎么保证可靠性?简单说就是每个Partation都分配给副本,做数据同步,保证数据不丢失。

副本同步策略(ISR):

  • kafka不是完全同步,也不是完全异步,是一种ISR机制,先来了解下完全同步的优势劣势

    完全同步的优点:同样为了容忍N台节点的故障,过半机制需要 2N+1 个副本,而全部同步方案只需要 N+1 个副本,

    而 Kafka 的每个分区都有大量的数据,过半机制方案会造成大量数据的冗余。

    完全同步缺陷:假设就有这么一个follower延迟太高或者某种故障的情况出现,导致迟迟不能与leader进行同步。

    • 等:就会造成数据延迟及其严重。

    • 不等:就说不上完全同步。

    所以就有了Kafka所谓的完全同步策略ISR。那么什么叫做ISR呢?咱们先了解几个概念:

    1. AR(Assigned Repllicas)一个partition的所有副本(就是replica,不区分leader或follower)

    2. ISR(In-Sync Replicas)能够和 leader 保持同步的 follower + leader本身 组成的集合。

    3. OSR(Out-Sync Relipcas)不能和 leader 保持同步的 follower 集合

    4. 公式: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.messages 
    • replica.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中。