1. 前言

前一段时间研究了大规模日志流高吞吐并行存储,通过深入研究Kafka的底层存储机制。我们发现Kafka的Zero-Copy零拷贝技术采用的是Java底层FileTransferTo方法,后期我们尝试了对TransferTo性能及其并行性能进行测试。以及后面在Kafka上面实现了并行TransferTo方法,并应有到了Apache Kafka系统中。

2. 消息存储机制

Kafka是一个分布式消息订阅——发布系统,无论是发布还是订阅,都须指定Topic。Topic只是一个逻辑的概念。每个Topic都包含一个或多个Partition,不同Partition可位于不同节点。同时Partition在物理上对应一个本地文件夹,每个Partition包含一个或多个Segment,每个Segment包含一个数据文件和一个与之对应的索引文件。在逻辑上,可以把一个Partition当作一个非常长的数组,可通过这个“数组”的索引(offset)去访问其数据。

3. Kafka使用的zero-copy零拷贝技术

在Kafka中消息存储模式中,数据存储在底层文件系统中。当有Consumer订阅了相应的Topic消息,数据需要从磁盘中读取然后将数据写回到套接字中(Socket)。此动作看似只需较少的 CPU 活动,但它的效率非常低:首先内核读出全盘数据,然后将数据跨越内核用户推到应用程序,然后应用程序再次跨越内核用户将数据推回,写出到套接字。应用程序实际上在这里担当了一个不怎么高效的中介角色,将磁盘文件的数据转入套接字。

数据每遍历用户内核一次,就要被拷贝一次,这会消耗 CPU 周期和内存带宽。幸运的是,您可以通过一个叫 零拷贝— 很贴切 — 的技巧来消除这些拷贝。使用零拷贝的应用程序要求内核直接将数据从磁盘文件拷贝到套接字,而无需通过应用程序。零拷贝不仅大大地提高了应用程序的性能,而且还减少了内核与用户模式间的上下文切换。

Java 类库通过 java.nio.channels.FileChannel 中的 transferTo() 方法来在 Linux 和 UNIX 系统上支持零拷贝。可以使用 transferTo() 方法直接将字节从它被调用的通道上传输到另外一个可写字节通道上,数据无需流经应用程序。本文首先展示了通过传统拷贝语义进行的简单文件传输引发的开销,然后展示了使用 transferTo() 零拷贝技巧如何提高性能。

3.1 传统模式下的四次拷贝与四次上下文切换

考虑一下从一个文件中读出数据并将数据传输到网络上另一程序的场景

File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);

代码逻辑很简单,但实际上,拷贝的操作需要四次用户模式和内核模式间的上下文切换,而且在操作完成前数据被复制了四次。下图展示了数据是如何在内部从文件移动到套接字的:

这里涉及的步骤有:

  1. read() 调用(参见图2)引发了一次从用户模式到内核模式的上下文切换。在内部,发出 sys_read()(或等效内容)以从文件中读取数据。直接内存存取(direct memory access,DMA)引擎执行了第一次拷贝(参见图1),它从磁盘中读取文件内容,然后将它们存储到一个内核地址空间缓存区中。
  2. 所需的数据被从读取缓冲区拷贝到用户缓冲区,read() 调用返回。该调用的返回引发了内核模式到用户模式的上下文切换(又一次上下文切换)。现在数据被储存在用户地址空间缓冲区。
  3. send() 套接字调用引发了从用户模式到内核模式的上下文切换。数据被第三次拷贝,并被再次放置在内核地址空间缓冲区。但是这一次放置的缓冲区不同,该缓冲区与目标套接字相关联。
  4. send() 系统调用返回,结果导致了第四次的上下文切换。DMA 引擎将数据从内核缓冲区传到协议引擎,第四次拷贝独立地、异步地发生 。

使用中间内核缓冲区(而不是直接将数据传输到用户缓冲区)看起来可能有点效率低下。但是之所以引入中间内核缓冲区的目的是想提高性能。在读取方面使用中间内核缓冲区,可以允许内核缓冲区在应用程序不需要内核缓冲区内的全部数据时,充当 “预读高速缓存(readahead cache)” 的角色。这在所需数据量小于内核缓冲区大小时极大地提高了性能。在写入方面的中间缓冲区则可以让写入过程异步完成。

不幸的是,如果所需数据量远大于内核缓冲区大小的话,这个方法本身可能成为一个性能瓶颈。数据在被最终传入到应用程序前,在磁盘、内核缓冲区和用户缓冲区中被拷贝了多次。

3.2 Kafka使用的zero-copy零拷贝技术

再次检查传统场景,我们注意到第二次和第三次拷贝根本就是多余的。应用程序只是起到缓存数据并将其传回到套接字的作用而以,别无他用。数据可以直接从读取缓冲区传输到套接字缓冲区。transferTo() 方法就能够让您实现这个操作。

transferTo()方法调用

public void transferTo(long position, long count, WritableByteChannel target);

transferTo() 方法将数据从文件通道传输到了给定的可写字节通道。在内部,它依赖底层操作系统对零拷贝的支持;在 UNIX 和各种 Linux 系统中,此调用被传递到 sendfile() 系统调用中,如下面代码所示,下面代码将数据从一个文件描述符传输到了另一个文件描述符:

sendFile()系统调用

#include <sys/socket.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

上图所示的 transferTo() 方法时的步骤有:

  1. transferTo() 方法引发 DMA 引擎将文件内容拷贝到一个读取缓冲区。然后由内核将数据拷贝到与输出套接字相关联的内核缓冲区。
  2. 数据的第三次复制发生在 DMA 引擎将数据从内核套接字缓冲区传到协议引擎时。

改进的地方:我们将上下文切换的次数从四次减少到了两次,将数据复制的次数从四次减少到了三次(其中只有一次涉及到了 CPU)。但是这个代码尚未达到我们的零拷贝要求。如果底层网络接口卡支持收集操作 的话,那么我们就可以进一步减少内核的数据复制。在 Linux 内核 2.4 及后期版本中,套接字缓冲区描述符就做了相应调整,以满足该需求。这种方法不仅可以减少多个上下文切换,还可以消除需要涉及 CPU 的重复的数据拷贝。对于用户方面,用法还是一样的,但是内部操作已经发生了改变:

  1. transferTo() 方法引发 DMA 引擎将文件内容拷贝到内核缓冲区。
  2. 数据未被拷贝到套接字缓冲区。取而代之的是,只有包含关于数据的位置和长度的信息的描述符被追加到了套接字缓冲区。DMA 引擎直接把数据从内核缓冲区传输到协议引擎,从而消除了剩下的最后一次 CPU 拷贝。

4. FileTransferTo并行性能测试

接下来我们利用多线程的方法对FileTransferTo方法进行并行传输,希望通过并行IO的技术来提升读取底层文件系统的性能。

测试条件

  • CentOS release 5.10
  • Intel® Xeon® CPU E7420 @ 2.13GHz
  • 逻辑CPU个数 16
  • 16GB RAM
  • 测试文件大小:1.2GB

  • 疑问:并行处理的性能比串行处理的性能差
  • 项目链接https://github.com/Tjcug/kafkaParallelIO.

Kafka:Zero-Copy零拷贝相关推荐

  1. Netty、Kafka中的零拷贝技术到底有多牛?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:rrd.me/ggFBd 零拷贝,从字面意思理解就是数据不需 ...

  2. 深入探秘 Netty、Kafka 中的零拷贝技术!

    作者:ksfzhaohui 原文:juejin.im/post/5cad6f1ef265da039f0ef5df 零拷贝,从字面意思理解就是数据不需要来回的拷贝,大大提升了系统的性能.我们也经常在 J ...

  3. 为什么Kafka这么快[零拷贝(Zero-Copy)]?

    如果想理解Kafaka为什么这么快,得先看DMA是什么. DMA: 无论 I/O 速度如何提升,比起 CPU,总还是太慢.SSD 硬盘的 IOPS 可以到 2 万.4 万,但是我们 CPU 的主频有 ...

  4. kafka高性能揭秘:顺序写和零拷贝

    顺序写&MMF Zero Copy零拷贝 传统io: DMA: 直接内存访问 传统io一共经历了四次拷贝:其中内核空间到用户空间的拷贝.用户空间拷贝到内核缓冲区这两次拷贝是多余的. 零拷贝只需 ...

  5. Kafka的零拷贝技术

    kafka中的消费者在读取服务端的数据时,需要将服务端的磁盘文件通过网络发送到消费者进程,网络发送需要经过几种网络节点.如下图所示: 传统的读取文件数据并发送到网络的步骤如下: (1)操作系统将数据从 ...

  6. 零拷贝技术:mmap和sendfile

    概述 零拷贝,zero-copy, Zero-copy describes computer operations in which the CPU does not perform the task ...

  7. Linux 零拷贝方案

    一 什么是零拷贝(zero copy)? 零拷贝有什么优点? 1.1 什么是零拷贝? 零拷贝: 指的是在I/O过程中,用户空间和内核空间不需要进行CPU数据拷贝.零拷贝并不是指I/O过程中一次拷贝都没 ...

  8. 通俗易懂的Kafka零拷贝机制

    Kafka之所以那么快,其中一个很大的原因就是零拷贝(Zero-copy)技术,零拷贝不是kafka的专利,而是操作系统的升级,又比如Netty,也用到了零拷贝.下面我就画图讲解零拷贝,如果对你有帮助 ...

  9. 什么是零拷贝技术(Zero Copy)?

    千里之行,始于足下 什么是"零拷贝"技术 要想要了解"零拷贝"机制,首先要了解在什么地方会用到这个东西.试想一个场景:我们需要从磁盘读取一个文件,然后通过网络输 ...

最新文章

  1. 网站服务器部署注意事项,服务器部署改云部署注意事项
  2. 邯郸学院计算机专业是本科还是专科,邯郸学院是大学吗 是本科还是专科
  3. - The superclass javax.servlet.http.HttpServlet was not found on the Java
  4. 两向量点乘坐标运算_高三数学冲刺复习之向量小题的题型总结(含好用的补充公式)...
  5. Linux_异常_08_本机无法访问虚拟机web等工程
  6. 一道微软Python面试题(文末附python教程丶电子书资料分享)
  7. python类的数组属性_Python学习之数组类型一:
  8. asp.net高校宿舍后勤管理系统
  9. oracle查看视图定义语句_oracle中查询用户表/索引/视图创建语句
  10. keras-迁移学习-resnet101-踩过的坑
  11. zip保存数据和接口获取压缩包 jsZip
  12. PLC控制电机正反转原理图
  13. VMware vSphere 7 vCenter 7 ESXi 7 正式版 免费下载
  14. 大学生计算机基础实验文库,大学计算机基础实验指导书(ecxel)
  15. 七年级计算机教案部编,七年级信息技术教案新部编本.docx
  16. Web端测试——F12的代码调试与抓包
  17. 计算机辅助cad职称报考,计算机辅助设计绘图员(AUTO CAD)中级证
  18. CRM为3Com带来什么?
  19. linux cmd 字体,微软开源Cascadia Code新字体,该字体针对命令行和代码编辑器
  20. AP微积分极限考点总结及解析

热门文章

  1. json字符串转换成json对象,json对象转换成字符串,值转换成字符串,字符串转成值...
  2. WebStorm错误--无法显示文件夹目录
  3. 认识微软Visual Studio Tools for AI
  4. 2017-06-09 问题
  5. 将spark默认日志log4j替换为logback
  6. [译文]c#扩展方法(Extension Method In C#)
  7. BNF范式(巴科斯范式)简介
  8. bzoj1669 [Usaco2006 Oct]Hungry Cows饥饿的奶牛
  9. 刚安装了Fedora 33,尝尝鲜~,哈哈~~~
  10. file的open()和read()