SRE 必备知识 - Kafka 探秘之零拷贝技术

Kafka 为什么会使用操作系统零拷贝?本文解释传统拷贝、zero-copy、DMA、page cache、socket buffer、scatter-gather I/O 以及 SSL/TLS 对 Kafka 零拷贝的影响。

作者 Stanislav Kozlovski

核心摘要

  • Kafka 使用的零拷贝(zero-copy)不是“完全没有拷贝”,而是减少不必要的数据拷贝和用户态/内核态切换。
  • 传统文件发送路径中,数据会经历 page cache、应用程序缓冲区、socket buffer、NIC buffer 等多个环节,产生多次拷贝和模式切换。
  • Kafka 的零拷贝依赖操作系统能力,让磁盘数据进入 read buffer 后,不再拷贝到 Kafka broker 的用户态缓冲区,而是通过文件描述符和 scatter-gather I/O 直接进入网络发送路径。
  • 在示例路径中,传统拷贝有 4 次模式切换和 4 次数据拷贝;零拷贝后变成 2 次模式切换、2 次 DMA 拷贝和 1 次很小的指针拷贝。
  • 零拷贝并不总是 Kafka 性能的决定性因素:很多 Kafka 集群瓶颈更可能先出现在网络;启用加密和 SSL/TLS 后,Kafka 已经不能使用零拷贝。

如果你了解过 Kafka,那么它用到的一个性能优化技术可能会引起你的注意 – 操作系统的零拷贝(zero-copy)优化。

零拷贝操作可以避免对数据的非必要拷贝,当然,并非是说完全没有拷贝。

在 Kafka 的场景下,操作系统可以从 page cache 拷贝数据到 socket buffer,直接绕过 Kafka broker 这个 Java 程序。这可以节省一些额外的拷贝,节省一些用户态和内核态的切换。让我们看一个例子。

关键术语

  • page cache / read buffer:操作系统用于缓存磁盘文件内容的内存区域,原文图中称为 read buffer。
  • socket buffer:操作系统用于网络发送和接收的套接字缓冲区。
  • NIC buffer:网卡中的字节缓冲区。
  • DMA copy:DMA 是 Direct Memory Access 的缩写,是内存控制器的一个功能,可以避免 CPU 干预,允许硬件直接访问内存中的某些数据。
  • scatter-gather / Vectorized I/O:socket buffer 只保存 read buffer 中的数据指针,让 DMA 直接从内存读取数据,而不是把完整数据再复制一份。

传统拷贝

如果您的应用程序要从磁盘读取文件并通过网络发送它,则可能会进行一堆不必要的拷贝,以及用户态/内核态的切换。

Kafka 传统拷贝

在这个例子中,我们有 4 次模式切换(用户态和内核态之间的切换)和 4 次数据拷贝。

  • 应用程序(这里指 Kafka)利用 DMA copy 从磁盘 load 数据到 read buffer(用户态->内核态
  • read buffer 到应用程序的缓存区(内核态->用户态
  • 应用程序要发数据到网络上,实际是先写到 socket buffer(用户态->内核态
  • socket buffer 到 NIC buffer(响应数据写完之后,由内核态返回用户态)

零拷贝

Kafka 零拷贝

为了减少拷贝,把数据从磁盘直接发向网络,那 Kafka 在存储数据的时候,就要保证存储的数据格式和将要发出的 response 格式一致。

在传统拷贝模式下,第二步、第三步没啥意义,因为 Kafka 没有对数据做额外处理,只是简单转发。那能否从磁盘直接发向网络呢?答案是肯定的。

通过零拷贝技术,磁盘上的数据还是要先进入 read buffer,然后不用再拷贝到应用程序的缓存区,而是直接拷贝到 NIC buffer。图上的步骤 2:Appends just file descriptors,只是把文件描述符交给了 socket buffer,实际数据并没有拷贝给 socket buffer。

这就是所谓的 scatter-gather 操作,也称为 Vectorized I/O。scatter-gather 是仅将 read buffer 数据指针存储在 socket buffer 中,并让 DMA 直接从内存读取数据的行为。

最终结果如何呢?

  • 4 次模式切换变成了 2 次
  • 2 次 DMA 拷贝,仍然是 2 次
  • 1 次微小的指针拷贝

Kafka 传统拷贝和零拷贝对比

联系我们交流

在 Kafka 中的真实影响

你可能听过 Kafka 因为零拷贝实现了高性能,但是理想很丰满现实很骨感,零拷贝技术在大部分 Kafka 集群中并没有那么大的影响力。

  • CPU 很少成为瓶颈。网络饱和的速度要快得多,因此在大多数情况下,内存中副本的缺失并不会带来多大的影响。
  • 启用加密和 SSL/TLS 已经禁止 Kafka 使用零拷贝

因此,更准确的表述是:零拷贝是 Kafka 高性能路径中的一个重要优化,但不能把 Kafka 性能简单归因于零拷贝。对于真实集群,网络带宽、磁盘、批量发送、客户端消费能力、加密配置等因素都可能决定最终吞吐。

结论

Kafka 零拷贝的核心价值,是在 broker 不需要处理消息内容、只需要把磁盘中的数据发送给网络时,减少用户态和内核态之间的无效搬运。它降低了拷贝次数和模式切换次数,但不是“完全没有拷贝”,也不是所有 Kafka 场景的主要性能来源。

如果 Kafka 集群启用了 SSL/TLS,或者瓶颈已经出现在网络层,零拷贝带来的收益就会被明显削弱。排查 Kafka 性能问题时,应该把零拷贝作为一个机制理解,而不是把它当成唯一优化答案。

FAQ

Q1:零拷贝是不是完全没有数据拷贝? A:不是。原文强调,零拷贝是避免非必要拷贝,并非完全没有拷贝。在示例中,零拷贝后仍然有 2 次 DMA 拷贝和 1 次很小的指针拷贝。

Q2:Kafka 零拷贝绕过了谁? A:在 Kafka 场景下,操作系统可以从 page cache 走向网络发送路径,绕过 Kafka broker 这个 Java 程序的用户态缓冲区,减少额外拷贝和用户态/内核态切换。

Q3:scatter-gather 在这里是什么意思? A:它指 socket buffer 只保存 read buffer 的数据指针,让 DMA 直接从内存读取数据,而不是把完整数据再复制到 socket buffer。

Q4:为什么 SSL/TLS 会影响 Kafka 零拷贝? A:原文结论是启用加密和 SSL/TLS 后,Kafka 已经禁止使用零拷贝。因为数据发送前需要经过加密处理,不能再只是把磁盘中的原始数据绕过应用层直接发出去。


  • 原文:Zero Copy Basics
  • 译者:秦晓辉,极客时间专栏《运维监控系统实战笔记》作者,Open-Falcon、Nightingale 开源项目发起人,作为联创创办了 Flashcat ,专攻监控/可观测性方向。欢迎和我一起探讨监控/可观测性相关技术和产品。
延伸路径

继续看解决方案和产品对比

如果你正在做监控、可观测性或故障定位相关选型,建议从解决方案和产品对比继续往下看。

标签 Kafka
快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云