零拷贝和非零拷贝有什么区别,零拷贝通俗理解

首页 > 经验 > 作者:YD1662022-10-24 22:34:18

大文件传输用什么方式实现?

那针对大文件的传输,我们应该使用什么方式呢?

我们先来看看最初的例子,当调用 read 方法读取文件时,进程实际上会阻塞在 read 方法调用,因为要等待磁盘数据的返回,如下图:

零拷贝和非零拷贝有什么区别,零拷贝通俗理解(17)

具体过程:

对于阻塞的问题,可以用异步 I/O 来解决,它工作方式如下图:

零拷贝和非零拷贝有什么区别,零拷贝通俗理解(18)

它把读操作分为两部分:

而且,我们可以发现,异步 I/O 并没有涉及到 PageCache,所以使用异步 I/O 就意味着要绕开 PageCache。

绕开 PageCache 的 I/O 叫直接 I/O,使用 PageCache 的 I/O 则叫缓存 I/O。通常,对于磁盘,异步 I/O 只支持直接 I/O。

前面也提到,大文件的传输不应该使用 PageCache,因为可能由于 PageCache 被大文件占据,而导致「热点」小文件无法利用到 PageCache。

于是,在高并发的场景下,针对大文件的传输的方式,应该使用「异步 I/O 直接 I/O」来替代零拷贝技术。

直接 I/O 应用场景常见的两种:

另外,由于直接 I/O 绕过了 PageCache,就无法享受内核的这两点的优化:

于是,传输大文件的时候,使用「异步 I/O 直接 I/O」了,就可以无阻塞地读取文件了。

所以,传输文件的时候,我们要根据文件的大小来使用不同的方式:

在 Nginx 中,我们可以用如下配置,来根据文件的大小来使用不同的方式:

location /video/ { sendfile on; aio on; directio 1024m; }

当文件大小大于 directio值后,使用「异步 I/O 直接 I/O」,否则使用「零拷贝技术」。

零拷贝和非零拷贝有什么区别,零拷贝通俗理解(19)

总结

早期 I/O 操作,内存与磁盘的数据传输的工作都是由 CPU 完成的,而此时 CPU 不能执行其他任务,会特别浪费 CPU 资源。

于是,为了解决这一问题,DMA 技术就出现了,每个 I/O 设备都有自己的 DMA 控制器,通过这个 DMA 控制器,CPU 只需要告诉 DMA 控制器,我们要传输什么数据,从哪里来,到哪里去,就可以放心离开了。后续的实际数据传输工作,都会由 DMA 控制器来完成,CPU 不需要参与数据传输的工作。

传统 IO 的工作方式,从硬盘读取数据,然后再通过网卡向外发送,我们需要进行 4 上下文切换,和 4 次数据拷贝,其中 2 次数据拷贝发生在内存里的缓冲区和对应的硬件设备之间,这个是由 DMA 完成,另外 2 次则发生在内核态和用户态之间,这个数据搬移工作是由 CPU 完成的。

为了提高文件传输的性能,于是就出现了零拷贝技术,它通过一次系统调用(sendfile 方法)合并了磁盘读取与网络发送两个操作,降低了上下文切换次数。另外,拷贝数据都是发生在内核中的,天然就降低了数据拷贝的次数。

Kafka 和 Nginx 都有实现零拷贝技术,这将大大提高文件传输的性能。

零拷贝技术是基于 PageCache 的,PageCache 会缓存最近访问的数据,提升了访问缓存数据的性能,同时,为了解决机械硬盘寻址慢的问题,它还协助 I/O 调度算法实现了 IO 合并与预读,这也是顺序读比随机读性能好的原因。这些优势,进一步提升了零拷贝的性能。

需要注意的是,零拷贝技术是不允许进程对文件内容作进一步的加工的,比如压缩数据再发送。

另外,当传输大文件时,不能使用零拷贝,因为可能由于 PageCache 被大文件占据,而导致「热点」小文件无法利用到 PageCache,并且大文件的缓存命中率不高,这时就需要使用「异步 IO 直接 IO 」的方式。

在 Nginx 里,可以通过配置,设定一个文件大小阈值,针对大文件使用异步 IO 和直接 IO,而对小文件使用零拷贝。

零拷贝和非零拷贝有什么区别,零拷贝通俗理解(20)

上一页12345下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.