想象一个分区(Partition)的副本们是一个**“特战小队”**

  • Leader (队长): 负责接收和写入所有数据,对外发布命令。

  • Follower (队员): 负责跟随队长,完整复制队长的所有动作(数据)。


1. ISR 和 OSR 的概念

ISR (In-Sync Replicas) - “同步小队”

  • 概念: 指的是那些**“跟得上”队长的、健康的队员组成的集合。这个集合里永远包含队长自己**。

  • 评判标准: 一个队员是否在“同步小队”里,取决于它是否在规定时间(由参数 replica.lag.time.max.ms 控制,默认30秒)内成功地复制了队长的最新数据。

  • 作用: 当队长(Leader)阵亡时,必须从ISR(同步小队)里选出一个新的队长。这保证了新上任的队长拥有最接近完整的数据,最大限度地避免数据丢失。

OSR (Out-of-Sync Replicas) - “掉队小队”

  • 概念: 指的是那些因为网络延迟、Broker负载过高等原因,**“跟不上”**队长的、不健康的队员。

  • 状态变化: 如果一个ISR里的队员长时间没跟上进度,就会被“踢”出同步小队,降级到OSR(掉队小队)。反之,如果一个掉队的队员努力追赶,最终跟上了进度,它也能重新回到ISR。

总结:一个分区的所有副本 = ISR + OSR。 Kafka动态维护这两个列表。


2. 为什么说Kafka数据会丢失?

数据丢失主要发生在以下两种关键场景:

场景一:数据已写入Leader,但ISR未同步,Leader就宕机了

这是最典型的情况。

  1. 生产者发送一条消息给Leader。

  2. Leader成功写入了这条消息到自己的磁盘。

  3. 在Leader将这条消息同步给ISR中的Follower之前,Leader所在的Broker突然宕机了。

  4. Kafka从ISR中选举出一个新的Leader。

  5. 因为新的Leader(以及其他ISR成员)根本没收到过那条消息,所以这条消息就永久丢失了

如何缓解?——生产者acks参数

  • acks=1 (默认): Leader写入成功就返回ACK。有数据丢失风险(就是上面描述的场景)。

  • acks=all (或-1): Leader不仅要自己写入成功,还必须等待ISR中所有Follower都同步成功后,才向生产者返回ACK。

    • 优点: 这极大地提高了数据持久性,能有效防止上述场景的数据丢失。

    • 缺点: 牺牲了性能(延迟更高)。

场景二:为了可用性,选择了“不干净的”Leader选举

这是一个**“可用性 vs 数据一致性”**的经典权衡。

  1. 假设一个分区的Leader和ISR里所有的Follower都同时宕机了(比如机房断电)。

  2. 此时,只剩下OSR(掉队小队)里的副本还活着。

  3. Kafka面临一个选择:

    • 选择一 (默认,安全): unclean.leader.election.enable = false。
      坚持原则,绝不从OSR里选Leader。结果就是这个分区停止服务(不可用),直到ISR里的某个副本恢复。数据不会丢,但服务没了。

    • 选择二 (危险,不推荐): unclean.leader.election.enable = true。
      为了让服务尽快恢复,允许Kafka从OSR(掉队小队)里选一个成员当新的Leader。因为这个新Leader本身就是“掉队的”,它上面的数据是不完整的。当它成为Leader后,会以自己的数据为准,那么之前丢失的数据就再也找不回来了。这是用数据丢失换取服务可用性


精简总结

  • ISR/OSR是什么?

    • ISR是健康、同步的副本集合,是Leader的“预备队”。

    • OSR是掉队、滞后的副本集合,是“板凳球员”。

  • Kafka为什么会丢数据?

    1. 常规丢失: 消息写入Leader后,还没来得及同步给ISR所有成员,Leader就宕机了。(用acks=all可大概率避免)

    2. 极端丢失: 当整个ISR都挂掉时,如果为了恢复服务而强制从OSR中选举新Leader(开启了不安全设置),那么新Leader本身就缺数据,导致数据永久丢失。

Logo

加入社区!打开量化的大门,首批课程上线啦!

更多推荐