1.6.3 Append-only & 零拷贝
Last updated
Last updated
Append-Only的概念非常简单:每次新加入写文件,都只能附加到日志文件末尾
这种机制不需要bitmap来管理空闲空间,同时也更好地满足了顺序读写:
Kafka 在这部分涉及到了对 Java NIO 的使用,我对于这部分内容并不了解,但其中有关零拷贝的技术涉及到OS课程中提到的内容,因此也可以提出来讲讲。
零拷贝,顾名思义就是减少了数据流转过程中无意义的CPU执行数据搬运的过程。我们先来看正常情况下一个数据发送的例子:
用户程序想要通过网卡发送数据,要经历以下几个数据搬运过程:
从磁盘读数据到内核缓冲区(这一步由DMA完成数据搬运,不需要CPU)
用户程序通过系统调用陷到内核态,由CPU完成从内核缓冲区到用户应用程序缓冲区的数据搬运,完成后回到用户态
再次调用系统调用陷入内核,此时一般会进到网卡驱动,由CPU将用户数据搬运拷贝到 socket 缓冲区
由DMA将发送数据拷贝到网卡进行发送
不难看出,这样一个简单的网卡数据发送要经历很多次的数据拷贝搬运,且其中有两次不必要的CPU拷贝过程。CPU的时间是宝贵的,我们希望它去做一些有意义的工作,而不是在这把数据搬来搬去。于是,Linux提供了sendfile 系统调用来优化掉这些不必要的CPU拷贝过程:
可以看到,在新的sendfile模式下,从前“内核缓存->用户缓存->内核缓存”的冗余搬运过程被优化掉了,CPU只需要执行少量必要的信息拷贝,其余过程可以全部交给DMA实现。这就是所谓零拷贝的原理。
对Kafka而言,Kafka 通过 Java NIO 的 FileChannel 的 transferTo 和 transferFrom 方法实现零拷贝,这种利用操作系统底层实现来优化自身性能的设计是Kafka高性能的重要保障,其体现在kafka 设计的各个部分,我们之后还会再次看到这一点。