谈谈kafka中消息消费的零拷贝技术

  |   0 评论   |   5,114 浏览

kafka通常用来做消息队列中间件,它的高吞吐量其中一个重要功臣就是“零拷贝”。从字面上理解就是数据不需要多次拷贝,系统性能大幅度提升。其实,不仅在kafka中,Java NIO,netty,rocketMQ等框架中也都用到了零拷贝。要了解什么是零拷贝,需要从I/O的几个概念了解起。

缓存I/O

缓存I/O又被称作标准I/O,是大多少文件系统默认I/O。为了减少读盘的次数,同时也为了保护系统本身的安全,缓存I/O在一定程度上分离了内核空间和用户空间。但也因此,数据在传输过程中需要在用户空间和内核空间之间进行多次的拷贝,这些数据拷贝操作所带来的CPU以及内存开销是非常大的。

下图示例列出了一次缓存IO读和写需要经过的步骤:

对于缓存I/O,一个读操作有3次数据拷贝,一次写操作又会有3次的数据拷贝。

读操作:磁盘->内核缓存区->用户空间缓存区->应用程序内存。

写操作:应用程序内存->用户空间缓存区->Socket缓存区->网络。

直接I/O

直接IO就是指没有用户级的缓存区,但是内核缓存区还是有的。这样就减少一次从内核缓冲区到用户程序缓存的数据拷贝。如下图所示:

内存映射文件

首先,映射的意思就是建立一种一一对应关系,是指硬盘上文件的位置与进程逻辑地址的对应关系。这种对应关系纯属是逻辑上的概念,物理上是不存在的。在内存映射的过程中,并没有实际的数据拷贝,文件没有被载入内存,只是逻辑上被放入了内存,内存中实际只是一个逻辑地址。

如上图所示,数据不再经过应用程序内存,直接从内核缓存区到socket缓冲区。

零拷贝

零拷贝连内核缓存区到socket缓存区也省了,底层的网卡驱动程序直接读取内核缓存区的数据并发送到网络。在整个过程中,只发生了2次数据拷贝。一次是从磁盘到内核缓存区,另一次是从内核缓存区到网络。既然有发生数据拷贝,为什么还叫“零拷贝”,那是因为所说的零拷贝是指数据在内存中没有发生数据拷贝。

评论

发表评论

validate