Kafka 中所谓的 ‘零拷贝’ 技术到底是什么?
文章收录地址:Java-Bang
专注于系统架构、高可用、高性能、高并发类技术分享
除了消息顺序追加、页缓存等技术,Kafka 采用了零拷贝技术 来显著提升了性能。所谓零拷贝即为将数据直接从磁盘文件复制至网卡设备上,并无需通过应用程序之手。这一技术显著提升了应用程序的运行效率,在Linux操作系统中其核心基于底层的sendfile()函数实现。在Java语言层面,则实现了类似功能的技术是FileChannal.transferTo()方法的基本框架。
注
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
代码解释
首先执行 read() 函数以获取固定内容(假设为文件 A ),然后发送 write() 操作以将数据传输至 Socket 端口,请参见下图。

在这个过程中,文件 A 经历了4次复制 的过程:
调用 read() 时,文件 A 中的内容被复制到了内核模式下的 Read Buffer 中。
CPU 控制将内核模式数据复制到用户模式下。
在调用 write() 的时候,将用户模式下的内容复制至内核模式中的 Socket缓冲区中。
将内核模式下的 Socket Buffer 的数据复制到网卡设备中传送。
从上述分析可以看出,在内核模式与用户模式之间经历了完整的转换周期:首先发生了从内核模式到用户模式的一次完整转换(即第一次复制过程),随后又经历了一次从用户模式返回内核模式的过程(即第二次复制过程)。整个过程中涉及两次来回复制的操作:第一次是从内核到用户模式的复制操作;第二次是从用户模式返回到内核模式的逆向操作,在上述四步操作中分别对应第2步和第3步的操作步骤。值得注意的是,在这一过程中完成了四次不同方向的上下文切换过程:包括两次从内核到用户的切换以及两次从用户返回到内核的变化过程。
如果应用采用了零拷贝技术方案,则可以直接向内核发送请求以实现将位于磁盘中的数据传输至Socket。如图所示

零拷贝技术利用DMA(Direct Memory Access)技术将文件内容复制至内核模式下的ReadBuffer中。然而,并非所有的数据都被复制至SocketBuffer中;相反地,在SocketBuffer中仅存储了包含数据位置和长度信息的文件描述符。DMA引擎直接将数据从内核模式传递给网络接口设备(协议引擎)。此外,在这一过程中,数据仅经历了两次复制便被传输至网络适配器,并且上下文切换次数也减少为两次。零拷贝特性和效果是在内核模式下实现的。
要深入理解Kafka的核心机制不仅仅是其日志管理模块的内容还包括其存储层技术的相关知识这样才能对其整体架构有清晰的理解鼓励大家继续努力加油吧~打工人!

