Skip to content

Kafka数据可靠性保证

kafka副本核心概念

首先来介绍下Kafka副本角色与分工,Kafka 的每个分区(Partition)有多个副本(Replica),分为以下角色:

副本类型作用读写权限
Leader处理所有读写请求,负责与生产者/消费者交互读 + 写
Follower从 Leader 拉取数据保持同步,不处理客户端请求只读
Observer与 Follower 类似,但不参与 Leader 选举(Kafka 2.4+ 引入,用于跨地域同步)只读

AR与ISR

  1. AR(Assigned Replicas):分区的所有副本集合,包括 Leader 和 Follower。
  2. ISR(In-Sync Replicas):当前与 Leader 保持数据同步的副本集合(包含 Leader 本身)。
    • 动态管理:Follower 若在 replica.lag.time.max.ms(默认 30s)内未完成同步,会被移出 ISR;同步恢复后自动重新加入。
    • Leader 选举:仅 ISR 中的副本有资格成为新 Leader。
    • acks=all:需等待 ISR 中所有副本确认,而非所有 AR 副本。
  3. OSR(Out-of-Sync Replicas):未与 Leader 保持同步的副本集合。
    • OSR 副本无法参与 Leader 选举。
    • 常见场景:Broker 宕机或网络延迟过大时,副本会被划入 OSR。

副本同步

副本同步原理

  1. LEO:每个副本的"书签",记录当前写到哪里了;
    • Leader的LEO = 最新内容的位置
    • Follower的LEO = 当前抄写到的位置
  2. HW:高水印值,一定不会大于LEO值,小于 HW 值的消息被认为是“已提交”或“已备份”的消息,对消费者可见。
    • 消费者:只能读到HW之前的内容
    • 生产者:HW之后的数据可能被截断(如Leader切换时)
  3. Remote LEO:远程LEO,Leader记录的每个Follower的LEO。
    • 作用:Leader通过这些信息计算HW

最小同步副本数

定义:必须至少同步到N个节点才算成功。

properties
min.insync.replicas=2  // 至少需要Leader+1个Follower确认
acks=all               // 必须等待这2个站点都签收
java
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

// 设置可靠性参数
props.put(ProducerConfig.ACKS_CONFIG, "all");  // 等待所有同步副本确认
props.put("min.insync.replicas", 2); // 至少2个副本确认

假设我们一共配置了3个分区:

配置可靠性风险场景
min=1Leader宕机可能丢数据
min=2允许1个副本掉队
min=3任何副本宕机都会导致消息无法被消费

常见问题

  • Q1:为什么消费者看不到最新数据?

    • 答案:因为HW还没更新(最慢的快递员还没上报进度)
  • Q2:Leader挂了如何恢复?

    • 从ISR中选新Leader。
    • 新Leader对比所有Follower,以HW为基准删除不一致数据(所以此时可能丢数据,因为远程在同步中,但是主节点挂了,导致新选上来的Leader的HW数据低于真实的HW。)
    • 要求其他Follower按新Leader的数据重新同步。
  • Q3:如何避免Follower掉队?

    • 优化网络(减少快递运输时间)

    • 监控UnderReplicatedPartitions指标

    • 设置合理参数:

      properties
      replica.lag.time.max.ms=60000  // 允许1分钟延迟
      min.insync.replicas=2          // 3副本时允许1个故障

警告

最小同步副本数只有ACKS=ALL的时候才生效!