Kafka Zero Copy Technique (零拷贝 技术)

1. Summary

Kafka 的数据是持久化到每个 Partition 下的 .log 文件中的, 因此当需要消费已经持久化的消息时, 势必需要从磁盘中将数据读取到内存中, 并通过网卡发送给消费者. 之前我们已经说过, Kafka的消息消费是高性能, 那么是什么技术支撑了 Kafka 消息的高性能消费呢? 接下来就简单介绍一下 Kafka 高性能读取的秘密 - 零拷贝技术. 介绍零拷贝技术之前, 我们先介绍一下传统的数据文件拷贝过程.

2. 传统数据文件拷贝过程

传统的数据文件拷贝大概可以分成四个过程:

  1. 操作系统将数据从磁盘中加载到内核空间的 Read Buffer (页缓存区) 中.

  2. 应用程序将 Read Buffer 中的数据拷贝到应用空间的应用缓冲区中.

  3. 应用程序将应用缓冲区的数据拷贝到内核的 Socket Buffer 中.

  4. 操作系统将数据从 Socket Buffer 中发送到网卡, 通过网卡发送给数据接收方.

连起来看就是:

磁盘空间 -> 内核空间 Read Buffer -> 应用空间 Application Buffer -> 内核空间 Socket Buffer -> NIC (network interface card) Buffer -> Consumer

3. Kafka 零拷贝过程

所谓的零拷贝是指将数据在内核空间直接从磁盘文件复制到网卡中, 而不需要经由用户态的应用程序之手. 这样既可以提高数据读取的性能, 也能减少核心态和用户态之间的上下文切换, 提高数据传输效率.

在正式介绍零拷贝 (Zero Copy) 之前, 我们先简单介绍一下 DMA (Direct Memory Access) 技术. DMA, 又称之为直接内存访问, 是零拷贝技术的基石. DMA 传输将数据从一个地址空间复制到另外一个地址空间. 当 CPU 初始化这个传输动作, 传输动作本身是由 DMA 控制器来实行和完成. 传统的的内存访问都需要用 CPU 调度来完成, 因此通过DMA, 硬件则可以绕过 CPU, 自己去直接访问系统主内存. 很多硬件都支持 DMA, 其中就包括网卡, 声卡, 磁盘驱动控制器等.

有了 DMA 技术的支持之后, 网卡就可以直接区访问内核空间的内存, 这样就可以实现内核空间和应用空间之间的零拷贝了, 极大地提升传输性能. 下图展示了 Kafka 零拷贝的数据传输过程. 数据传输的的过程就简化成了:

  1. 操作系统将数据从磁盘中加载到内核空间的 Read Buffer (页缓存区) 中.

  2. 操作系统直接将数据从内核空间的 Read Buffer (页缓存区) 传输到网卡中, 并通过网卡将数据发送给接收方.

  3. 操作系统将数据的描述符拷贝到 Socket Buffer 中. Socket 缓存中仅仅会拷贝一个描述符过去, 不会拷贝数据到 Socket 缓存.

Kafka数据零拷贝的过程如下图所示:

磁盘空间 -> 内核空间 Read Buffer -> NIC Buffer -> Consumer
                |- 只拷贝描述符 -> 内核空间 Socket Buffer

通过零拷贝技术, 就不需要把 内核空间页缓存里的数据拷贝到应用层缓存, 再从应用层缓存拷贝到 Socket 缓存了, 两次拷贝都省略了, 所以叫做零拷贝. 这个过程大大的提升了数据消费时读取文件数据的性能. Kafka 从磁盘读数据的时候, 会先看看内核空间的页缓存中是否有, 如果有的话, 直接通过网关发送出去.

总结一下: Kafka用到的零拷贝技术, 主要是减少了核心态和用户态之间的两次数据拷贝过程, 使得数据可以不用经过用户态直接通过网卡发送到接收方, 同时通过 DMA 技术, 可以使 CPU 得到解放, 这样实现了数据的高性能传输 (比传统的方法快 3 倍左右).

Reference