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 从磁盘读数据的时候,会先看看内核空间的页缓存中是否有,如果有的话,直接通过网关发送出去。
代码实现:
importjava.io.File;importjava.io.RandomAccessFile;importjava.net.InetSocketAddress;importjava.nio.channels.FileChannel;importjava.nio.channels.SocketChannel;publicclassZeroCopy{publicstaticvoidmain(String[] args)throwsException{File file =newFile("xxxxxx.log");RandomAccessFile raf =newRandomAccessFile(file,"rw");FileChannel channel = raf.getChannel();//Opens a socket channel and connects it to a remote address.SocketChannel socketChannel =SocketChannel.open(newInetSocketAddress("192.168.2.222",9091));//Transfers bytes from this channel's file to the given writable byte channel.
channel.transferTo(0,channel.size(), socketChannel);}}
版权归原作者 一流觞 所有, 如有侵权,请联系我们删除。