基于本文回答

播面 播面

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

Broker所在服务器意外断电,未被操作系统刷入磁盘(Page Cache丢失)的那部分最新的日志会不会丢?

知识点图片

这是一个非常经典且核心的Kafka面试题和架构问题。

直接回答结论:对于这台断电的 Broker 本地磁盘来说,存在于 Page Cache 中未刷盘的数据确实会丢失。但是,从整个 Kafka 集群和业务的角度来看,这部分数据“会不会丢”,完全取决于你的集群副本策略和生产者的配置(主要是 acks 参数)。

Kafka 的设计哲学是:不依赖单机的硬件(如磁盘强行刷盘 fsync)来保证数据的可靠性,而是依赖分布式的多副本复制机制来保证。

下面我们分情况详细剖析:

一、 为什么数据会停留在 Page Cache?

Kafka 为了追求极致的吞吐量,默认情况下不会在收到每条消息时强制调用系统内核的 fsync 命令将数据刷入物理磁盘。
相反,Kafka 只是将数据写入到操作系统的内存(Page Cache)中,就认为本地写入成功了。至于什么时候真正写入磁盘,交由操作系统的后台线程(如 Linux 的 pdflush/flush 线程)异步决定。
因此,一旦服务器意外断电,内存(Page Cache)中的数据瞬间灰飞烟灭。


二、 决定数据是否(全局)丢失的关键因素

数据是否真的丢失,取决于发生断电时,这部分最新的数据是否已经复制到了其他的 Broker 节点上。这主要由生产者的 acks 参数和集群的 min.insync.replicas 参数决定:

1. 如果 Producer 配置了 acks=1(默认配置的一种,视版本而定)

  • 工作机制:只要 Leader 副本将数据写入到了本地的 Page Cache,就会给生产者返回“发送成功”的响应。
  • 断电场景:Leader 刚把数据写到 Page Cache,给 Producer 返回了成功。此时 Follower 副本还没来得及把数据拉取走,Leader 所在的服务器突然断电了。
  • 结果:数据永久丢失。 因为 Producer 以为发送成功了不会重试,而唯一拥有这条数据的机器内存清空了。等这台机器重启后,这部分未刷盘的数据就彻底不见了。

2. 如果 Producer 配置了 acks=0

  • 工作机制:发出去就不管了,根本不关心 Broker 收没收到。
  • 结果:极大概率丢失。 断电时不管在不在 Page Cache,只要没落盘且没被复制,都会丢。

3. 如果 Producer 配置了 acks=all (或 acks=-1) —— 【推荐的高可靠配置】

  • 工作机制:Leader 收到数据后,不仅写入自己的 Page Cache,还要等待 ISR(In-Sync Replicas,同步副本集合)中所有的 Follower 副本都拉取到这条数据(写入了它们的 Page Cache),Leader 才会给 Producer 返回“发送成功”。

  • 断电场景:Leader 所在的服务器意外断电,它的 Page Cache 数据丢失了。

  • 结果:数据不会丢失。

    • 因为在此之前,Follower 副本已经把数据拉走并保存在它们各自的机器上了。
    • Kafka 集群会立即发生 Leader 选举,将其中一个拥有最新数据的 Follower 提升为新的 Leader。
    • Producer 之前收到了成功响应,业务继续往下走;未收到成功响应的数据,Producer 会自动进行重试,发给新的 Leader。
  • 注意一个极端边界情况:如果你的 acks=all,但是此时 ISR 集合里只有 Leader 自己(例如其他节点都挂了或者网络延迟被踢出 ISR 了),那么此时断电,数据依然会丢失

  • 如何防范这种边界情况? 必须配合 Broker 端的参数 min.insync.replicas 使用。如果设置 min.insync.replicas=2,意味着至少要有 2 个副本(Leader 和至少 1 个 Follower)同步成功,才允许写入。如果 ISR 数量小于 2,Producer 会直接收到异常,从而避免了“假成功”导致的丢失。


三、 能不能强制 Kafka 每条消息都刷盘(避免 Page Cache 丢失)?

技术上可以,但极度不推荐。

Kafka 提供了两个参数:

  • flush.messages:每积累多少条消息,强制刷盘一次。
  • flush.ms:每隔多少毫秒,强制刷盘一次。

如果你设置 flush.messages=1,那么每收到一条消息,Kafka 都会调用 fsync 强制落盘。这样断电就不会丢本地数据了。
但是: 这样干会把 Kafka 退化成一个普通的、极其缓慢的系统,完全丧失了 Kafka 的高吞吐量优势。磁盘的随机写/甚至顺序写性能,远远比不上写内存的性能。

四、 总结

在服务器断电导致 Page Cache 丢失的情况下:

  1. 单机层面:那部分未刷盘的数据绝对丢失了。
  2. 系统层面会不会丢,取决于你的配置
    • 配置为 acks=0acks=1会丢失
    • 配置为 acks=all,且 min.insync.replicas >= 2,且集群有多台机器存活:不会丢失(依赖副本救场)。

行业最佳实践:不要试图通过强制刷盘来解决断电丢数据的问题,而是应该配置 acks=all + 多副本 + 合理的 min.insync.replicas,用软件层面的冗余来对抗硬件层面的单点故障(如断电)

00:00
00:00