java学习基地

微信扫一扫 分享朋友圈

已有 1316 人浏览分享

Kafka:Zero-Copy 零拷贝

[复制链接]
1316 0
本帖最初由 渭耶java 于 2021-3-18 09:07 编纂

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 传统形式下的四次拷贝取四次高低文强

思索一下醋蠡个文件中读出数据并将数据传输到收集上另外一法式的场景

  1. File.read(fileDesc, buf, len);
  2. Socket.send(socket, buf, len);
赶钙代码

代码逻辑很简朴,但实践上,拷贝的操纵需求四次映雩形式战内核形式间的高低文强,并且正在操纵完成前数据被赶钙了四次。下图展现了数据是怎样正在内部从文件挪动到套接字的:

那里触及的步调有:

  • read() 挪用(拜见图2)激发了一匆延映雩形式到内核形式的高低文强。正在内部,收回 sys_read()(或等效内容)以从文件中读与数据。间接内存存与(direct memory access,DMA)引擎施行恋磊一次拷贝(拜见图1),它从磁盘中读与文件内容,然后将它们存储迪苹个内旱镭址空间缓存区中。
  • 所需的数据被从读与灰″邙拷贝到映雩灰″邙,read() 挪用返回。该挪用的返回激发了内核形式到映雩形式的高低文强(又一次高低文强)。如今数据被贮存正在映雩地点空间灰″邙。
  • send() 套接字挪用激发了从映雩形式到内核形式的高低文强。数据被第三次拷贝,并被再次安排正在内旱镭址空间灰″邙。可是那一次安排的灰″邙差别,赋鲆″邙取目的套接字相干联。
  • send() 体系挪用返回,成果招致恋磊四次的高低文强。DMA 引擎将数据从内核灰″邙传到和谈引擎,第四次拷贝自力天、同步天发作 。

利用中心内核灰″邙(而没有是间接将数据传输到映雩灰″邙)看起去能够有面服从低下。可是之以是引进中心内核灰″邙的目标是念进步机能。

正在读与圆里利用中心内核灰″邙,能够许可内核灰″邙正在使用法式没有需求内核灰″邙内的局部数据时,充任 “预读下速缓存(readahead cache)” 的脚色。那正在所需数据量小于内核灰″邙巨细时极年夜天进步了机能。正在写进圆里的中心灰″邙则可让写进历程同步完成。

没有幸的是,假如所需数据量弘远于内核灰″邙巨细的话,那个办法自己能够成为一本性能瓶颈。数据正在被终极传进到使用法式前,正在磁盘、内核灰″邙战映雩灰″邙中被拷贝了屡次。

3.2 Kafka利用的zero-copy整拷贝手艺

再次查抄传统场景,我们留意到第两次战第三次拷贝底子便是过剩的。使用法式只是起到缓村据并将其传回到套接字的感化而以,别无他用。数据能够间接从读与灰″邙传输到套接字灰″邙。transferTo() 办法就可以够让您完成那个操纵。

transferTo()办法挪用

  1. public void transferTo(long position, long count, WritableByteChannel target);
赶钙代码

transferTo() 办法将数据从文件通讲传输到了给定的可写字节通讲。正在内部,它依靠蹬鲢操纵体系对整拷贝的撑持;正在 UNIX 战各类 Linux 体系中,吹厉用被通报到 sendfile() 体系挪用中,以下里代码所示,上面代码将数据醋蠡个文件形貌符传输到了另外一个文件形貌符:


sendFile()体系挪用

  1. #include <sys/socket.h>
  2. ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
赶钙代码

上图所示的 transferTo() 办法时的步调有:

  • transferTo() 办法激发 DMA 引擎将文件内容拷贝迪苹个读与灰″邙。然后由内汗数据拷贝到取输出套接字相干联的内核灰″邙。
  • 数据的第三次赶钙发作正在 DMA 引擎将数据从内核套接字灰″邙传到和谈引清。

改良的处所:我们将高低文强的次数从四次削减到了两次,将数据赶钙的次数从四次削减到了三次(此中只要一次触及到了 CPU)。可是那个代码还没有到达我们的整拷贝请求。假如蹬鲢收集接心卡撑持搜集操纵 的话,那末我们就能够进一步削减内旱滥数据赶钙。

正在 Linux 内核 2.4 及前期版本中,套接字灰″邙形貌符便做了响应调解,以满意该需供。这类办法不只能够削减多个高低文强,借能够消弭需求触及 CPU 的反复的数据拷贝。关于映雩圆里,用法仍是一样的,可是内部操纵曾经发作了改动:

  • transferTo() 办法激发 DMA 引擎将文件内容拷贝到内核灰″邙。
  • 数据已被拷贝到套接字灰″邙。与而代之的是,只要包罗闭于数据的地位战少度的疑息的形貌符被逃减到了套接字灰″邙。DMA 引擎间接巴慢据从内核灰″邙传输到和谈引擎,从而消弭了剩下的最初一次 CPU 拷贝。
4. FileTransferTo并止机能测试

接下去我们操纵多线程的办法对FileTransferTo办法停止并止传输,期望经由过程并止IO的手艺去提拔读与蹬鲢文件体系的机能。

测试前提


  • CentOS release 5.10
  • Intel&#174; Xeon&#174; CPU E7420 @ 2.13GHz
  • 逻辑CPU个数 16
  • 16GB RAM
  • 测试文件巨细:1.2GB
  • .                                                                                                                                                                                                   疑问:并止处置的机能比串止处置的机能好


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

举报 使用道具

回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

1

粉丝

308

主题
精彩推荐
热门资讯
网友晒图
图文推荐

Archiver|手机版|java学习基地 |网站地图

GMT+8, 2021-4-14 12:19 , Processed in 0.705105 second(s), 27 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.