为什么 Apache Kafka 不需要 Fsync 来保证安全?


Apache Kafka 不需要 fsyncs 来确保安全,因为它在其复制协议中包含恢复。它是一个真实世界的分布式系统,使用异步日志写入 + 恢复,并内置一些额外的额外安全性。异步日志写入使其能够在各种硬件和各种工作负载上提供强大的性能。

什么是 fsync / flush?
术语“fsync”和“flush”是指操作系统调用(称为 sys 调用),可确保写入文件的数据物理存储在存储驱动器上。它用于将文件的内存状态与其磁盘状态同步。
基本上,如果写入数据但未执行 fsync,然后计算机本身崩溃、重新启动或断电,则这些文件更改将不会保留。
Kafka 不会同步刷新——这意味着,默认情况下,它不会总是在确认消息之前刷新。在我们解释为什么异步刷新对 Apache Kafka 没问题之前,让我们看看为什么它们对 Raft 不安全。

Kafka 的数据复制协议被设计为在没有 fsyncs 的情况下是安全的。Kafka 复制不依赖于用于领导人选举的主题分区的完整性,而是依赖于外部元数据存储,例如 ZooKeeper 或 KRaft。主题分区可能会丢失一些消息,而不会影响数据复制协议本身的正确性。

为了应对某个 broker 上部分消息的丢失,Kafka 内置了恢复或自愈机制,可以自动修复数据。这种恢复机制使 Kafka 在没有 fsync 的情况下变得安全。

异步日志写入一直是分布式系统社区中大量研究的主题
步日志写入有一个缺点——同时崩溃会导致数据丢失。

在某些情况下规模非常大,我看到集群崩溃发生,例如级联 OOM 在高负载下导致集群崩溃,或者导致所有节点几乎同时崩溃的错误。

Kafka 不受此问题的影响,因为它不会将未刷新的数据存储在自己的内存中,而是存储在页面缓存中

如果 Kafka 崩溃,数据不会再见,因此 Kafka 实际上比没有日志的 BookKeeper 更安全——尽管两者都使用恢复协议。

Kafka 复制和恢复
所有异步写入存储的分布式系统都有一个内置的恢复机制,允许受影响的节点恢复由于节点突然终止而丢失的任何数据。
所有这些恢复机制都有以下共同的规则:

  1. 受影响的节点必须从对等节点恢复丢失的数据。
  2. 在受影响的节点至少恢复了之前丢失的数据之前,它不能成为领导者的候选人。

Kafka 的恢复过程非常简单。  

  1. 失败的代理重新启动,丢失了一些未成功存储到磁盘的消息。假设日志有 1000 条消息,但丢失了最后十条消息,这意味着最后的偏移量现在是 990。
  2. 经纪人已从 ISR(领导候选人的法定人数)中删除。代理从现有主题分区领导者的偏移量 991 处开始获取消息,并将消息添加到自己的日志中。前十条消息恢复了之前丢失的消息。
  3. 一旦经纪人被追上,它就能够作为一个功能齐全的经纪人加入 ISR,成为领导的候选人。

关键是,在受影响的代理赶上(并恢复任何丢失的数据)之前,它不能成为领导者,因此不会有数据丢失。这个节点在至少恢复它丢失的东西之前不会成为领导者候选者的概念是我所知道的所有三种恢复协议背后的基本原则。

为什么 Raft 需要 fsyncs
Raft 协议本质上是一组服务器,其中每个服务器运行相同的逻辑,并由持久保存到磁盘的操作日志作为备份。该协议包括领导者选举、故障检测、数据复制、更改集群成员资格等。

Raft 集群不能容忍丢失任何先前写入磁盘的日志条目。Raft 依赖于日志本身来确保协议的正确性,因此如果一个节点上的日志丢失数据,它可能会危及整个集群的正确性。 

如果一个条目被写入磁盘,但随后服务器崩溃并丢失了该条目,Raft 可能会丢失存储在其他服务器上的该数据的副本——也就是说,在一个服务器上丢失一个条目可能会导致所有服务器都丢失该条目!因此每个 Raft 服务器都必须 fsync 数据写入磁盘。

详细点击标题