基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

假设一个Topic设置了3个副本(Replication Factor),min.insync.replicas为2。现在挂了一台Broker,此时Producer还能写吗?如果再挂一台呢?

知识点图片

这是一个非常经典的 Kafka 面试题,涉及到 Kafka 的高可用机制、ISR(In-Sync Replicas)集合以及 Producer 的 acks 配置。

结论先行:

  1. 挂了一台 Broker 时:Producer 还能正常写
  2. 再挂一台 Broker 时(共挂了 2 台):Producer 能否写入取决于其 acks 参数的配置。如果 acks=all,则不能写;如果 acks=0acks=1,则能写

下面为你详细剖析原因:

核心前置概念

  • Replication Factor = 3:Topic 的数据有 3 个副本(1 个 Leader,2 个 Follower)。
  • ISR (In-Sync Replicas):与 Leader 保持同步的副本集合。正常情况下,3 个副本都在 ISR 中(ISR = 3)。
  • min.insync.replicas = 2:这是 Broker 端的配置,意思是当 Producer 设置 acks=all(或 -1)时,必须至少有 2 个副本(包含 Leader 在内)成功写入,这次写入才算成功。注意:这个参数只在 acks=all 时生效!

场景一:挂了一台 Broker

假设集群完全健康时,ISR 集合里有 3 个副本。
此时挂了一台 Broker(包含该 Topic 的一个副本):

  • ISR 变化:挂掉的副本会被踢出 ISR 集合,此时 ISR 数量 = 2
  • 能否写入?
    • 无论 Producer 的 acks 设置为 0、1 还是 all,都能正常写入
    • 因为哪怕是要求最严格的 acks=all,当前 ISR 的数量(2)依然满足 min.insync.replicas=2 的最低要求。写入时,Leader 和剩下的那个 Follower 都落盘后,就会给 Producer 返回成功。

场景二:再挂一台 Broker(总共挂了 2 台)

此时,3 个副本中挂了 2 个,整个集群关于这个 Topic 的 Partition 只剩下最后 1 个存活的副本(且它必定是 Leader)。

  • ISR 变化:第二个挂掉的副本也被踢出 ISR 集合,此时 ISR 数量 = 1
  • 能否写入?这完全取决于 Producer 的 acks 配置:

1. 如果 Producer 配置 acks=all(或 -1

  • 结果不能写入(写入失败)
  • 原因:当 acks=all 时,Broker 会检查当前的 ISR 数量。此时 ISR=1,小于配置的 min.insync.replicas=2。Broker 会拒绝这次写入,并向 Producer 抛出 NotEnoughReplicasException 异常。
  • 意义:系统为了保证数据的绝对安全,宁愿牺牲可用性(拒绝写入),也不愿意在只有一个副本存活的情况下接收数据(防止这最后一条独苗也挂了导致数据彻底丢失)。

2. 如果 Producer 配置 acks=1

  • 结果能写入成功
  • 原因acks=1 的意思是,只要 Leader 成功写入本地日志,就给 Producer 返回成功。此时 Broker 根本不会去检查 min.insync.replicas 的值。由于剩下的那个存活的副本就是 Leader,所以它可以正常接收数据并返回成功。
  • 风险:如果在此时 Leader 也挂了,由于数据还没来得及同步给其他 Follower(其他都挂了),这条数据就会丢失。

3. 如果 Producer 配置 acks=0

  • 结果能写入成功(对 Producer 而言)。
  • 原因acks=0 是“发送即忘(Fire and Forget)”模式,Producer 把消息发出去就认为成功了,根本不关心 Broker 有没有存下来,更不会管什么 min.insync.replicas

总结与生产实践

在真实的生产环境中,为了兼顾高可用(HA)高可靠(不丢数据),业界最标准的黄金配置组合就是:

  • Replication Factor = 3(3 副本)
  • min.insync.replicas = 2(最少 2 副本同步)
  • acks = all(Producer 确认所有 ISR 写入)

这种组合的优势在于:
它允许集群在宕机 1 台机器的情况下,依然能对外提供高可靠的读写服务;如果宕机 2 台,则停止写入以保护数据不丢,此时消费者依然可以消费已有的数据(只读不写)。

00:00
00:00