1、传统的拷贝

传统的数据文件拷贝过程如下图所示,大概可以分成四个过程:

磁盘----》read buffer-----》application buffer-------》socket buffer---------》网卡-------》发送给消费者

在这里插入图片描述

2. Kafka零拷贝过程

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

在正式介绍零拷贝结束(Zero-Copy)之前,我们先简单介绍一下DMA(Direct Memory Access)技术。DMA,又称之为直接内存访问,是零拷贝技术的基石。DMA 传输将数据从一个地址空间复制到另外一个地址空间。当CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实行和完成。因此通过DMA,硬件则可以绕过CPU,自己去直接访问系统主内存。很多硬件都支持DMA,其中就包括网卡、声卡、磁盘驱动控制器等。
有了DMA技术的支持之后,网卡就可以直接区访问内核空间的内存,这样就可以实现内核空间和应用空间之间的零拷贝了,极大地提升传输性能。下图展示了Kafka零拷贝的数据传输过程。数据传输的的过程就简化成了:

磁盘------》readbuff--------》网卡推送

在这里插入图片描述

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

代码实现:

import java.io.File;
import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;

public class ZeroCopy {
    public static void main(String[] args) throws Exception {
        File file  = new File("xxxxxx.log");

        RandomAccessFile raf = new RandomAccessFile(file, "rw");

        FileChannel channel = raf.getChannel();

        //Opens a socket channel and connects it to a remote address.
        SocketChannel socketChannel = SocketChannel.open(
                new InetSocketAddress("192.168.2.222", 9091)
        );

        //Transfers bytes from this channel's file to the given writable byte channel.
        channel.transferTo(0,channel.size(), socketChannel);
    }
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐