基于本文回答
0
评论

如果 Kafka 集群中一台机器突然掉电,数据会丢失吗?

知识点图片

这是一个非常经典的 Kafka 面试题和生产实践问题。

简短的回答是:取决于你的 Kafka 集群和生产者的配置。

Kafka 的设计理念是通过多机副本来保证数据的可靠性,而不是依赖单机的磁盘同步(fsync)。如果配置得当,一台机器突然掉电绝对不会丢失数据;但如果使用了默认或者追求极致性能的配置,数据可能会丢失。

具体是否会丢失,我们需要从以下几个维度来详细拆解:

1. 生产者确认机制 (acks 配置)

这是决定数据是否丢失的最关键因素。当生产者发送消息给 Kafka 时,有一个 acks 参数:

  • acks = 0:生产者发完数据就不管了。如果此时数据刚发到网卡,机器就掉电了,数据丢失
  • acks = 1(默认值,较老版本):只要 Leader 副本所在的机器接收到数据并写入内存(Page Cache),就向生产者返回成功。如果此时 Leader 机器突然掉电,且数据还没有来得及同步给 Follower 副本,数据丢失
  • acks = all (或 -1):Leader 必须等待所有 ISR(In-Sync Replicas,同步副本集合)中的机器都接收到数据后,才向生产者返回成功。只要 ISR 中还有存活的机器,单机掉电不会丢失数据

2. 最小同步副本数 (min.insync.replicas)

即使你设置了 acks = all,如果配置不当,依然会丢数据。
假设你的副本因子 (replication.factor) 是 3,但是某段时间内网络抖动,另外两台 Follower 都掉线了,此时 ISR 列表里只剩下 Leader 自己。
这时候 acks = all 实际上退化成了 acks = 1。如果此时这台 Leader 机器掉电,数据依然会丢失

  • 如何防止? 必须在 Broker 或 Topic 级别设置 min.insync.replicas >= 2。这样当 ISR 列表里少于 2 台机器时,Kafka 会拒绝接收新数据,宁可牺牲可用性,也要保证不丢数据。

3. “脏页”与掉电的致命关系(Page Cache)

这是一个非常底层的细节,也是“突然掉电”这个场景最特殊的地方。

  • Kafka 为了极高的吞吐量,默认情况下不会将每条消息强制刷入磁盘(调用 fsync),而是交给了操作系统的 Page Cache(内存),由操作系统决定何时刷盘。
  • 掉电意味着内存中的数据瞬间清空。如果一台机器掉电,它缓存在 Page Cache 中尚未刷入磁盘的数据会全部消失。
  • 那 Kafka 是怎么保证安全的? Kafka 的哲学是:我不相信单机的磁盘,我只相信多台机器的内存。 只要你配置了 acks=all 和多副本,哪怕机器 A 掉电丢了内存里的数据,机器 B 和机器 C 的内存/磁盘里还有这份数据。Kafka 会迅速选举 B 或 C 成为新的 Leader,继续对外提供服务。

4. 脏 Leader 选举 (unclean.leader.election.enable)

假设一台机器掉电了,它是 Leader。此时需要选举新的 Leader。

  • 如果存活的机器中,没有一台是属于 ISR(完全同步)列表里的(即剩下的机器数据落后于掉电的机器),怎么办?
  • 如果 unclean.leader.election.enable = true:Kafka 会允许让落后的机器成为新 Leader。这意味着服务恢复了,但是掉电机器上多出来的那部分数据彻底丢失了
  • 如果 unclean.leader.election.enable = false(现代版本默认):Kafka 会宁死不屈,拒绝选举,导致该 Partition 不可用,直到掉电的机器重启恢复。这样不会丢失数据

总结:如何配置才能保证单机掉电绝对不丢数据?

如果你希望在单机甚至少数几台机器掉电的情况下,数据绝对安全(银行/金融级配置),必须同时满足以下条件:

  1. Topic 副本数replication.factor >= 3 (至少有 3 份数据)
  2. 生产者配置acks = all (或 -1) (必须等大家都有了才算成功)
  3. Broker/Topic 配置min.insync.replicas >= 2 (至少有 2 台机器确认收到数据)
  4. Broker 配置unclean.leader.election.enable = false (绝不允许落后的副本当 Leader)

只要满足上述 4 点,集群中一台机器突然掉电,甚至主板烧毁,你的数据也安然无恙。

右滑查看面试常问