使用批量消息提升服务端处理能力

Kafka提供了单词发送一条消息的send方法,但实际上,Kafka的客户端在实现消息发送时,采用了异步批量发送的机制。也就是说,当你调用send时,它并不会立即将消息发出去,而是放在缓存当中,到合适的时机把缓存中消息组成一批一次性发送给Broker。

而接收端,Kafka不会把一批消息还原成多条,而是每条消息都当作批消息来处理,在Broker整个处理流程中,这些被组合在一起的消息始终都是一个整体,不会被拆开。

使用顺序读写提升磁盘 I/O性能

对于磁盘来说,它有一个特性,就是顺序读写的性能要远远好于随机读写。因为操作系统每次从磁盘读写数据的时候,需要先寻址,也就是先要找到数据在磁盘上的物理位置,然后再进行数据读写。所以随机读写会花费大量时间在寻址上,而顺序读写只需要找到第一个位置,接着往下写久可以了。

Kafka存储设计非常简单,对于每个分区,它把从Producer 收到的消息,顺序地写入对应的 log 文件中,一个文件写满了,就开启一个新的文件这样顺序写下去。消费的时候,也是从某个全局的位置开始,也就是某一个 log 文件中的某个位置开始,顺序地把消息读出来。

利用PageCache 加速消息读写

PageCache 就是操作系统在内存中给磁盘上的文件建立的缓存。无论我们使用什么语言编写的程序,在调用系统的 API 读写文件的时候,并不会直接去读写磁盘上的文件,应用程序实际操作的都是 PageCache,也就是文件在内存中缓存的副本。

Kafka 在读写消息文件的时候,充分利用了 PageCache 的特性。一般来说,消息刚刚写入到服务端就会被消费,按照 LRU 的“优先清除最近最少使用的页”这种策略,读取的时候,对于这种刚刚写入的 PageCache,命中的几率会非常高。

ZeroCopy:零拷贝技术

服务端处理消费的逻辑大致如下:

1、找到消息所在的文件,然后读入内存当中。

2、把消息通过网络发送给客户端。

这个过程中,数据实际上做了 2 次或者 3 次复制:

1、如果PageCache中没有,则需要将消息从文件复制到PageCache。

2、从PageCache读取到应用程序的内存空间中。

3、从应用程序复制到Socket的缓冲区。

而Kafka采用的是直接从PageCache复制到Socket中,这样可以省略一次复制。

参考

《消息队列高手课》