为什么Kafka的速度那么快

 阅读大约需要1分钟

为什么Kafka的速度那么快

我们都知道Kafka是基于磁盘进行存储的,但Kafka官方又称其具有高性能、高吞吐、低延时的特点,其吞吐量动辄几十上百万。

一般认为在磁盘上读写数据是会降低性能的,因为寻址会比较消耗时间,那么Kafka又是怎么做到其吞吐量动辄几十上百万的呢?

kafka的高性能是底层设计、分布式partition存储、高效利用磁盘和操作系统特性、批量压缩等,综合产生的结果。
一、利用Partition实现并行处理

我们知道Kafka是一个Pub-Sub的消息系统,无论是发布还是订阅,都要指定Topic,Topic只是一个逻辑的概念。每个Topic都包含一个或多个Partition,不同Partition可位于不同节点。

一方面由于不同Partition可位于不同机器,因此可以充分利用集群优势,实现机器间的并行处理。

另一方面由于Partition在物理上对应一个文件夹,即使多个Partition位于同一个节点,也可通过配置让同一节点上的不同Partition置于不同的磁盘上,从而实现磁盘间的并行处理,充分发挥多磁盘的优势。

二、顺序写磁盘

由于存储介质的特性,磁盘本身存取就比主存慢,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分之一甚至几千分之一,怎么样才能提高磁盘的读写效率呢?

有以下两种方法:

    1. 预读或者提前读;
    1. 合并写——多个逻辑上的写操作合并成一个大的物理写操作中; 即采用磁盘顺序读写(不需要寻道时间,只需很少的旋转时间)。 仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。Kafka中每个分区是一个有序的,不可变的消息序列,新的消息不断追加到partition的末尾,这个就是顺序写。
三、利用page cache+mmap

即便是顺序写入磁盘,磁盘的访问速度还是不可能追上内存。所以Kafka的数据并不是实时的写入硬盘,它充分利用了现代操作系统分页存储来利用内存提高I/O效率。

page cache(os cache):【操作系统自己管理的缓存】以Page为单位,缓存文件内容。

mmap即Memory Mapped Files内存文件映射,mmap其实就是把物理上的磁盘文件的一些地址和page cache地址进行一层映射,使得进程像读写磁盘一样读写内存,定时有os帮助我们将数据刷写到磁盘

Kafka在写入磁盘文件的时候,可以直接写入这个os cache里,也就是仅仅写入内存中, 接下来由操作系统自己决定什么时候把os cache里的数据真的刷入磁盘文件中。通过这一个步骤, 就可以将磁盘文件写性能提升很多了,因为其实这里相当于是在写内存,不是在写磁盘。

四、零拷贝

Kafka在读取磁盘时做了哪些优化?

  • 基于sendfile实现zero copy

Linux2.4+ 内核通过sendfile系统调用提供了零拷贝。数据通过DMA拷贝到内核态Buffer后,直接通过DMA拷贝到NIO Buffer,无需CPU拷贝。 这也是零拷贝这一说法的来源。除了减少数据拷贝外,因为整个读文件的网络发送由一个sendfile调用完成,整个过程只有两次上下文切换,因此大大提高了性能。

Kafka在这里采用的方案是通过NIO的transferTo/transferFrom调用操作系统的sendfile实现零拷贝, 总共发生2次内核数据拷贝,2次上下文切换和一次系统调用,消除了CPU数据拷贝。

五、批量处理

在很多情况下,系统的瓶颈不是CPU或磁盘,而是网络IO。 因此除了操作系统提供的低级批处理之外,Kafka的客户端和broker还会在通过网络发送数据之前, 在一个批处理中累积多条记录 (包括读和写)。记录的批处理分摊了网络往返的开销,使用了更大的数据包从而提高了带宽利用率。

六、数据压缩

Producer可将数据压缩后发送给broker,从而减少网络传输代价,目前支持的压缩算法有:snappy、gzip、lz4、zstd。数据压缩一般都是和批处理配套使用来作为优化手段的。

总结为什么kafka速度那么快:

  • partition并行处理
  • 顺序写磁盘,充分利用磁盘特性
  • 利用了现代操作系统分页存储Page Cache来利用内存提高I/O效率
  • 采用了零拷贝技术
  • producer生产的数据持久化到broker,采用mmap文件映射,实现顺序的快速写入
  • customer从broker读取数据,采用sendfile系统调用,将磁盘文件读到OS内核缓冲区后,转到 NIO buffer进行网络发送,减少CPU消耗
  • 把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络IO损耗。