当前位置:网站首页>聊聊消息队列高性能的秘密——零拷贝技术
聊聊消息队列高性能的秘密——零拷贝技术
2022-07-02 06:33:00 【程序员柒柒】
前言
RocketMQ为什么这么快、Kafka为什么这么快?用了零拷贝技术?什么是零拷贝技术,它们二者的零拷贝技术有不同吗?
为什么需要零拷贝
在计算机产业中,I/O的速度相较CPU,总是太慢的。SSD硬盘的IOPS可以达到2W、4W,但是我们CPU的主频有2GHz以上,也就意味着每秒会有20亿次的操作。如果对于I/O操作,都是由CPU发出对应的指令,然后等待I/O设备完成操作之后返回,那CPU有大量的时间其实都是在等待I/O设备完成操作。但是,这个 CPU 的等待,在很多时候,其实并没有太多的实际意义。我们对于 I/O 设备的大量操作,其实都只是把内存里面的数据,传输到 I/O 设备而已。在这种情况下,其实 CPU 只是在傻等而已。特别是当传输的数据量比较大的时候,比如进行大文件复制,如果所有数据都要经过 CPU,实在是有点儿太浪费时间了。因此计算机工程师们就发明了DMA技术,也就是直接内存访问(Direct Memory Access)技术,来减少CPU等待的时间。
DMA技术
本文不做过多相关介绍,这里我简单总结下对它的理解。
如上所述,CPU资源很宝贵,如果用它来处理I/O那么将是极大的损失,比如说我们用千兆网卡或者硬盘传输大量数据的时候,如果都用CPU来搬运的话,肯定是忙不过来,所以可以选择DMAC(DMA控制器即DMA Controller,简称DMAC),CPU告诉DMAC它需要传输什么数据,从哪里传输,传输到哪里去这些信息,然后交给DMAC去做,DMAC可以等到数据都到齐了,再发送信号,交给CPU去处理,而不是让CPU在哪里忙等待。(DMAC:我们不加工数据,只是数据的搬运工)
具体传输过程(从磁盘传输到网络)如图:
零拷贝
如上我们发现,虽然通过DMA技术能够使得CPU不用忙等待I/O操作,减轻了一些压力,但是从图中也能清晰地看出,两次CPU的Copy完全是在搞笑的,能不能把这两个步骤去掉呢?这就是零拷贝需要做的事情了,而我们熟知的RocketMQ、Kafka都是使用了零拷贝技术来优化I/O,而它们的零拷贝处理方式却有些不同。
Kafka零拷贝——SendFile
Kafka的代码调用了Java NIO库,具体是FileChannel里面的transferTo方法(底层是。我们的数据并没有读到中间的应用内存里面,而是直接通过Channel,写入到对应的网络设备里。并且对于Socket的操作,也不是写入到Socket的Buffer里面,而是直接根据描述符(Descriptor)写入到网卡的缓冲区里面。于是,在这个过程中,只进行了两次数据传输。(由于没有在用户态内存层里面去Copy数据,干掉了两次CPU的Copy,所以我们将之称为零拷贝(Zero-Copy)
SendFile的工作原理
系统调用sendfile()通过DMA把磁盘数据拷贝到kernel buffer(read buffer),然后数据被kernel直接拷贝到另外一个与socket相关的kernel buffer(socket buffer)。这样就没有用户态和内核态之间的切换,从内核中直接完成了从一个buffer到另一个buffer的拷贝,因为数据就在kernel里。
如图:
第一次,是通过 DMA,从硬盘直接读到操作系统内核的读缓冲区里面。第二次,则是根据 Socket 的描述符信息,直接从读缓冲区里面,写入到网卡的缓冲区里面。
这是Kafka目前实时数据传输管道的标准解决方案,也是Kafka高吞吐的秘密之一,零拷贝。
RocketMQ零拷贝——Mmap
Mmap全称Memory Mapped Files。简单描述其作用就是:将磁盘文件映射到内存,用户通过修改内存就能修改磁盘文件。
它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射,完成映射之后你对物理内存的操作会被同步到磁盘上(操作系统在适当的时候)。
通过mmap也有一个很明显的缺陷——不可靠,写到mmap中的数据并没有被真正地写到磁盘,操作系统会在程序主动调用flush的时候才把数据真正写到磁盘。
RocketMQ主要通过MappedByteBuffer对文件进行读写操作。其中,利用了NIO中的FileChannel模型将磁盘上的物理文件直接映射到用户态的内存地址中(这种Mmap的方式减少了传统IO将磁盘文件数据在操作系统内核地址空间的缓冲区和用户应用程序地址空间的缓冲区之间来回进行拷贝的性能开销),将对文件的操作转化为直接对内存地址进行操作,从而极大地提高了文件的读写效率(正因为需要使用内存映射机制,故RocketMQ的文件存储都使用定长结构来存储,方便一次将整个文件映射至内存)。
如图:
总结
- CPU比I/O性能好很多,应当尽力给CPU让步,让它去做更多的事情,于是就有了DMA。DMA对CPU说,"你告诉我搬什么数据,搬到哪里,搬好了我告诉你,你先去忙别的"
- 我们发现,在数据传输过程中,有两次CPU的Copy可以省去,于是就有了内存映射技术(Mmap)、SendFile技术(内核数据Copy),让CPU不需要再白忙活了
- 市面上熟知的优秀中间件如RocketMQ使用的零拷贝技术是Mmap、Kafka使用的则是SendFile
边栏推荐
- Sqli labs level 12
- 使用递归函数求解字符串的逆置问题
- C language - Blue Bridge Cup - 7 segment code
- WSL installation, beautification, network agent and remote development
- Leetcode sword finger offer brush questions - day 22
- Pclpy projection filter -- projection of point cloud to cylinder
- Loadbalancer dynamically refreshes Nacos server
- Luogu greedy part of the backpack line segment covers the queue to receive water
- Minecraft插件服开服
- Sqli labs level 8 (Boolean blind note)
猜你喜欢
Solution of Xiaomi TV's inability to access computer shared files
WSL installation, beautification, network agent and remote development
Function ‘ngram‘ is not defined
Linux安装Oracle Database 19c
OpenShift 容器平台社区版 OKD 4.10.0部署
Openfeign facile à utiliser
Linux安装Oracle Database 19c RAC
Minecraft install resource pack
队列的基本概念介绍以及典型应用示例
OpenFeign 簡單使用
随机推荐
Aneng logistics' share price hit a new low: the market value evaporated by nearly 10 billion yuan, and it's useless for chairman Wang Yongjun to increase his holdings
【Go实战基础】gin 如何设置路由
gocv opencv exit status 3221225785
Gocv image reading and display
Servlet全解:继承关系、生命周期、容器和请求转发与重定向等
Programmer training, crazy job hunting, overtime ridiculed by colleagues deserve it
寻找链表中值域最小的节点并移到链表的最前面
There is a problem with MySQL installation (the service already exists)
Dip1000 runaway
Tcp/ip - transport layer
Qt——如何在QWidget中设置阴影效果
Sqli labs (post type injection)
小米电视不能访问电脑共享文件的解决方案
Judge whether it is Sudoku
C Baidu map, Gaode map, Google map (GPS) longitude and latitude conversion
Connect function and disconnect function of QT
gocv opencv exit status 3221225785
Qt的拖动事件
First week of JS study
Flink-使用流批一体API统计单词数量