消息队列_14(Kafka如何实现高性能IO)

Iola ·
更新时间:2024-09-21
· 551 次阅读

Kafka如何实现高性能IO? 1.使用批量消息提升服务端处理能力

kafka内部,消息都是以“批”为单位处理的。

消息在kafka中的流转:

发送端(Producer)
kafka的Producer只提供了单条返送的send()方法,并没有提供任何批量发送的接口。当调用send()方法发送一条消息之后,无论是同步还是异步发送,这条消息不会发送出去,会先缓存起来,然后选择合适的时机把缓存中的所有消息组成一批,一次性发给Broker。 服务端(Broker)
不会把一批消息再还原成多条消息,再一条一条处理。在Broker整个处理流程中,无论是写入磁盘、从磁盘读出来、还是复制到其他副本这些流程中,批消息都不会被解开,一直是作为一条“批消息”来进行处理的。 消费时
同样以批为单位进行传递的,Consumer从Broker拉到一批消息后,客户端把批消息解开,再一条一条交给用户代码处理。

构建批消息和解开批消息分别在发送端和消费端的客户端完成,不仅减轻了Broker的压力,最重要的是减少了Broker处理请求的次数,提升了总体的处理能力。

2. 使用顺序读写提升磁盘IO性能

对于磁盘,顺序读写性能远远好于随机读写。顺序读写相比随机读写省去了大部分的寻址时间,它只需要寻址一次。
Kafka利用了这个存储特性。存储设计简单,对于每个分区,它把从Producer收到的消息,顺序地写入对应log文件,一个文件写满后,开启一个新的文件这样顺序写下去。消费的时候,也顺序的读取。

3.利用PageCache加速消息读写

PageCache就是操作系统在内存中给磁盘的文件建立缓存。在调用系统的API读写文件是,不会直接读取磁盘上的,而是操作的是PageCache,也就是文件在内存中缓存的副本。

写文件:数据 — 写入 —> 内存的PageCache ——一批一批写入—— > 磁盘
读文件:从PageCache中读取数据

PageCache中有数据,直接读取,节省从磁盘上读取数据的时间 PageCache中没有数据,操作系统会引发一个缺页中断,应用程序的读取线程会被阻塞,操作系统把数据从文件中复制到PageCache中,然后应用程序再从PageCache中继续吧数据读取出来。其中的读磁盘操作会比较慢。

使用完PageCache后,不会立即清除,而是尽可能利用空闲内存保留,内存不足时,使用清理策略(LRU或者它的变种算法)清理掉部分PageCache。保留逻辑:优先保留最近一段时间最常使用的PageCache。

大部分情况下,消费读消息都会命中PageCache,好处:

读取的速度非常快 给写入消息让出磁盘的IO资源,简介提升了写入的性能 4. ZeroCopy: 零拷贝技术

在服务端,处理消费的大致逻辑:

从文件中找到消息数据,读到内存中 把消息通过网络发给客户端

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

从文件复制到PageCache中,如果命中PageCache,这一步可以省掉; 从PageCache复制到应用程序的内存空间中,也就是我们可以操作的对象所在的内存; 从应用程序的内存空间复制到Socket的缓冲区,这个过程就是调用网络应用框架的API发送数据的过程

kafka利用零拷贝技术可以减少一次复制,2、3步骤合并为一次。直接从PageCache中把数据复制到Socket缓冲区,减少一次复制,由于不用把数据复制到用户内存空间,DMA控制器可以直接完成数据复制,不需要CPU参与,速度更快。

系统调用:

#include ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

前两个参数:目的端和远端的文件描述符,后两个参数:远端的偏移量和复制数据的长度,返回值是实际复制数据的长度。


作者:窝是一只程序猿



io 队列 kafka 消息队列

需要 登录 后方可回复, 如果你还没有账号请 注册新账号