RocketMQ和Kafka的零拷贝区别

919 阅读6分钟

Linux中的零拷贝技术

  1. mmap+write
  2. sendfile

mmap

mmap 是一种内存映射技术,mmap系统调用使得进程之间通过映射同一个相同文件实现共享内存。mmap相比较于传统的IO来说,其实就是少了1次CPU拷贝而已。

传统的数据拷贝(四次拷贝-两次DMA拷贝两次CPU拷贝)过程:

image.png

image.png

基于mmap实现的拷贝(三次拷贝-两次DMA拷贝一次CPU拷贝)过程:

image.png

传统 IO 里面从内核缓冲区到用户缓冲区有一次 CPU 拷贝,从用户缓冲区到 Socket 缓冲区又有一次 CPU 拷贝。mmap 则一步到位,直接基于 CPU 将内核缓冲区的数据拷贝到了 Socket 缓冲区。
之所以能够减少一次拷贝,就是因为 mmap 直接将磁盘文件数据映射到内核缓冲区,这个映射的过程是基于 DMA 拷贝的,同时用户缓冲区是跟内核缓冲区共享一块映射数据的,建立共享映射之后,就不需要从内核缓冲区拷贝到用户缓冲区了。
虽然减少了一次拷贝,但是上下文切换的次数还是没变。
RocketMQ 中就是使用的 mmap 来提升磁盘文件的读写性能。

基于sendFile实现的拷贝(2次拷贝-两次DMA拷贝)过程:

image.png

首先,它可以替代前面的 read() 和 write() 这两个系统调用,这样就可以减少一次系统调用,也就减少了 2 次上下文切换的开销。其次,该系统调用,可以直接把内核缓冲区里的数据拷贝到 socket 缓冲区里,不再拷贝到用户态,这样就只有 2 次上下文切换,和 3 次数据拷贝

紧接着,如果网卡还支持SG-DMA的技术,则不仅会放弃使用CPU进行拷贝而且可以直接从内存缓冲区直接拷贝至网卡当中。在网络这一方面,又减少了一次拷贝,总共只需要两次拷贝、两次用户态内核态切换,性能又一步提升!当然,这项技术的前提都需要Linux内核2.1以上的版本!

image.png

cpu拷贝相较于DMA拷贝性能对比

比喻:相同一份文件,一次CPU拷贝每次100ms,一次DMA拷贝每次10ms,主要耗时在CPU拷贝

mmap和sendfile优缺点

mmap优点

  1. 跨平台性: MMap 提供了跨平台的文件映射方法,可以在不同操作系统上使用相同的代码进行文件映射,而不需要特定于操作系统的实现。
  2. 性能优势: MMap 可以提供较高的性能,特别适用于随机访问文件。它允许将文件的一部分或全部映射到内存中,这有助于减少磁盘 I/O 操作。
  3. 零拷贝: MMap 可以实现零拷贝,避免了数据在内核和用户空间之间的额外拷贝。这有助于提高性能和降低内存开销。
  4. 灵活性: MMap 允许应用程序以内存映射的方式对文件进行读写,从而具有更大的灵活性和控制权。

MMap 的缺点:

  1. 内存消耗: MMap 可能会占用大量内存,特别是在处理大文件时。这可能导致系统内存资源受限。
  2. 适用范围有限: MMap 更适用于随机访问文件,不如 SendFile 适用于顺序读取大型文件。
  3. I/O 操作不直接: MMap 操作是通过内存进行的,因此不如 SendFile 直接进行 I/O 操作。这可能导致某些情况下的性能下降。

mmap缺点

  1. 内存消耗: MMap 可能会占用大量内存,特别是在处理大文件时。这可能导致系统内存资源受限。
  2. 适用范围有限: MMap 更适用于随机访问文件,不如 SendFile 适用于顺序读取大型文件。
  3. I/O 操作不直接: MMap 操作是通过内存进行的,因此不如 SendFile 直接进行 I/O 操作。这可能导致某些情况下的性能下降。

SendFile 的优点:

  1. 适用于大文件传输: SendFile 更适用于顺序读取大型文件,它可以将文件的内容直接传输到网络,而不需要将文件加载到内存中。
  2. 内存效率: SendFile 在处理大文件时通常具有较低的内存开销,因为它不需要将整个文件映射到内存中。
  3. 直接 I/O 操作: SendFile 允许直接在文件和网络套接字之间进行 I/O 操作,减少了数据在内核和用户空间之间的拷贝。

SendFile 的缺点:

  1. 不适用于随机访问: SendFile 不适合随机访问文件,因为它主要用于顺序文件传输。
  2. 操作复杂性: SendFile 在使用时相对复杂,需要额外的参数设置和操作。
  3. 限制性: SendFile 的可用性受操作系统和服务器软件的支持程度的限制。

为什么RocketMQ选择mmap?

  1. 跨平台性: MMap 提供了一种跨平台的文件映射机制,可以在不同操作系统上使用相同的代码实现文件映射,而不需要根据操作系统进行不同的优化。这有助于确保 RocketMQ 在多种操作系统上的兼容性。
  2. 性能和可扩展性: MMap 具有较高的性能和可扩展性。它允许按需将文件的一部分或全部映射到内存中,而无需提前知道文件的大小。这对于 RocketMQ 这种需要高吞吐量和低延迟的消息传输系统非常重要。
  3. 精细控制: MMap 提供了更精细的控制,允许在需要时进行文件的部分读写,而不需要将整个文件传输到网络。这有助于优化网络性能和资源利用率。
  4. 通用性: MMap 可以用于各种文件传输场景,而 SendFile 更适用于顺序文件传输。由于 RocketMQ 可能需要处理多种不同类型的消息传输,MMap 提供了更通用的解决方案。

为什么Kafka选择SendFile?

  1. 性能和效率: SendFile 提供了高性能的文件传输机制,特别适合大文件的顺序传输。它可以通过将文件内容直接传输到网络套接字来实现高效的消息传输,而不需要将整个文件加载到内存中。对于 Kafka 这种需要处理大量消息的分布式消息系统,这种高效性能非常重要。
  2. 内存消耗: 使用 MMap 可能会导致大量内存消耗,特别是当需要同时处理多个文件时。在大规模的消息处理场景中,这可能导致系统内存资源受限。
  3. 适合大文件: Kafka 通常需要处理大型日志文件,这些文件在发送和接收时可以非常大。SendFile 更适合处理大文件,而不需要加载整个文件到内存中。
  4. 直接 I/O 操作: SendFile 允许直接在文件和网络套接字之间进行 I/O 操作,减少了数据在内核和用户空间之间的拷贝。这有助于提高性能和降低系统开销。
  5. 可扩展性: SendFile 适用于大规模的消息传输场景,并且可以轻松扩展以满足高吞吐量的需求。