1.在磁盘只做 Sequence I/O 顺序读写
kafka 生产者写数据是有序的,即 Partition 内部有序,数据以 append 的方式顺序追加写入。Consumer 消费数据也是有序的,指定 offset 后顺序读出 offset 之后的数据。顺序读写可以避免磁盘读数据时的多次寻道和旋转延迟
2.传统的IO流程
举个例子说明传统IO流程,比如:从磁盘读取数据,然后从Socket发送到网络
传统IO流程:
1、第一次:将磁盘文件,读取到操作系统内核缓冲区;
2、第二次:将内核缓冲区的数据,copy到application应用程序的buffer;
3、第三步:将application应用程序buffer中的数据,copy到socket网络发送缓冲区(属于操作系统内核
的缓冲区);
4、第四次:将socket buffer的数据,copy到网卡,由网卡进行网络传输。
* 传统方式,读取磁盘文件并进行网络发送,经过的四次数据copy是非常繁琐的。实际IO读写,需要进行
IO中断,需要CPU响应中断(带来上下文切换),尽管后来引入DMA来接管CPU的中断请求,但四次copy是存在
不必要的拷⻉的。
3.Sendfile 零拷⻉
Linux2.1内核开始引入了sendfile函数,用于将文件通过socket传送 ,同时在Linux2.4内核做了重大优化,将零拷⻉推到顶峰
优化后的处理过程如下:
1.将文件拷⻉到kernel buffer中;
2.向socket buffer中追加当前要发生的数据在kernel buffer中的位置和偏移量;
3.根据socket buffer中的位置和偏移量直接将kernel buffer的数据copy到网卡设备中;
* 经过上述过程,数据只经过了2次copy就从磁盘传送出去了。这个才是真正的Zero-Copy(这里的零拷⻉
是针对kernel来讲的,数据在kernel模式下是Zero-Copy)。
4.PageCache 机制
PageCache 功能是底层操作系统提供的,用于缓存文件的⻚数据,Kafka 重度依赖它实现大吞吐量和低延迟。 相对于 JVM 的缓存,PageCache没有 GC,减少开销,即使 Kafka 重启PageCache 还在,回收 PageCache 的代价小,而且只要生产者与消费者的速度相差不大,消费者会直接读取之前生产者写入 Page Cache 的数据,没有磁盘 IO。