基于磁盘读写的Kafka为什么那么快?
我们都知道Kafka一大特点就是快,每秒甚至可以达到百万级别的吞吐量,然后这种级别的吞吐量居然还是基于磁盘的读写,那么kafka是如何做到的呢?接下来我们就一起来分析下其中的奥妙。磁盘顺序写对于一般的机械硬盘来说如果要查找某个数据,需要先寻址,然后通过机械运动(磁头臂驱动磁头找到对于的磁道、扇面)来读取数据,这种飘忽不定的查询方式就造成了大量的时间消耗在了机械运动上,磁头被不停的移来移去,所以说我
我们都知道Kafka一大特点就是快,每秒甚至可以达到百万级别的吞吐量,然后这种级别的吞吐量居然还是基于磁盘的读写,那么kafka是如何做到的呢?接下来我们就一起来分析下其中的奥妙。
磁盘顺序写
对于一般的机械硬盘来说如果要查找某个数据,需要先寻址,然后通过机械运动(磁头臂驱动磁头找到对于的磁道、扇面)来读取数据,这种飘忽不定的查询方式就造成了大量的时间消耗在了机械运动上,磁头被不停的移来移去,所以说我们一般说的磁盘读写慢实际上更强调的是磁盘随机读写慢。
所以相对随机读写,顺序读写就快很多了,因为顺序读写不需要大量的机械运动了,从而大大提高了磁盘读写效率。
举个例子:外卖小哥给一栋楼的住户送外卖,假如顺序是先5楼,3楼,1楼,4楼,2楼,就这就是随机,还有一种方式是1,2,3,4,5这就是顺序。这样大家一看就明白了,如果按照第一种随机方式估计你就吃不到外卖了。。。
那么Kafka是如何利用顺序读写的呢?
答案就是Kafka是通过追加的方式写入数据,每一批消息都是被追加到文件的尾部,并且读取时也不支持随机访问,只能顺序读取(可以从指定位置的offset开始顺序读取)。
批处理
一块普通的机械硬盘通过顺序读写就能大幅提升读写性能,是一种非常不错的,高性价比的优化方式,不过毕竟是物理硬件,终归有其瓶颈,如果存在频繁的小数据量的读写请求,那么即使采用了顺序读写效率也往往达不到预期,于是Kafka就想出了批处理的方式,每条消息产生后并不是立刻就发送出去了,而是等一等,等到了一定的大小(默认是16KB,kafka生产者消息发送的流程与参数配置,这篇文章有关于批次的使用方式。)后再打成一个批次发送出去,通过这样的方式就大大减少了Kafka与磁盘的IO交互,从而提升了Kafka的整体吞吐量。
页缓存
在linux读写文件时,页缓存可以用于缓存文件的逻辑内容,从而加快对磁盘上映像和数据的访问,一般一页大小为4K。它就相当于操作系统中的内存缓存一样,Kafka实际上在写文件时并不是直接写到磁盘上,而是写到页缓存中,再由操作系统自行决定什么时候将页缓存中的数据刷到磁盘中。
Kafk仅仅通过操作系统的页缓存技术,就变相的实现了内存读写的方式,避免了使用java的内存(如果使用java的内存必须要考虑垃圾回收带来的stop the world问题,这必然会带来性能的下降),从而进一步提升了性能。
零拷贝
当消费者从broker中拉取消息时,实际上kafka需要将消息从磁盘读取然后再给消费者,我们都知道传统的这一个过程需要经历4次数据copy和4次操作系统上下文切换,但是kafka利用了零拷贝技术,避免了磁盘数据复制到应用程序的过程,kafka读取时先看page cache中是否有数据,如果有直接从page cache拷贝到网卡设备(如果有DMA的支持,可只将描述符拷贝到socket缓冲区。操作系统缓冲区的内存地址和内存偏移量),否则从磁盘拷贝到page cache再拷贝到网卡设备,所以如果性能调优做的优秀,大多数消息就可以通过page cache获取,经历一次copy即可完成数据的传输,相当于在内存中完成了数据的读写。
传统的拷贝方式(4次拷贝和4次上下文切换)
1、执行read,操作系统从用户态切换到内核态,通过DMA将磁盘上的数据拷贝到内核空间的读缓冲区(read buffer)。
2、数据从内核空间的读缓冲区拷贝到用户缓冲区(user buffer),从内核态切换到用户态,此时用户可以操作数据。
3、执行write,从用户态切换到内核态,数据从用户缓冲区拷贝到内核空间的网络缓冲区(socket buffer)。
4、数据再从网络缓冲区拷贝到协议引擎,从内核态切换到用户态。
带收集功能的sendFile(2次拷贝和2次上下文切换)
1、执行read,操作系统从用户态切换到内核态,通过DMA将磁盘上的数据拷贝到内核空间的读缓冲区(read buffer)。
2、把数据的地址和偏移量追加到socket buffer。
3、DMA直接从把数据从内核空间的读缓冲区拷贝到协议引擎,内核态切换回用户态。
在Java中,FileChannel的transferTo() 方法可以实现这个过程。
以上几种就是关于Kafka压榨性能的方式,当然Kafka中的分区结构也是大大提高吞吐量的一种设计方式,可以说Kafka的设计考虑了从硬件到软件的各个方面,从而才能在基于磁盘的存储前提下,依然可以达到一个超高级别的吞吐量。
更多推荐
所有评论(0)