支持百万TPS,Kafka是怎么做到的?
所有大数据传输都会想到Kafka。Kafka被誉为大数据杀手。在业界拥有众多成熟的应用场景,并得到主流企业的认可。这款为大数据而生的消息中间件以其百万级TPS吞吐量而闻名,并迅速成为大数据界的宠儿,在数据采集、传输和存储过程中发挥着关键作用。
业界有很多成熟的消息中间件,比如:RabbitMQ、RocketMQ、ActiveMQ、ZeroMQ,为什么Kafka还能跻身众多对手之列,当然这取决于他强大的吞吐量。下面我们就来告诉你这个秘密。
Kafka如何支撑百万级TPS?
首先用思维导图直接给你答案:Kafka支撑百万TPS的秘诀
磁盘顺序读写
生产者都写数据,消费者都读数据顺序读和写入,先来张图直观感受一下顺序读写和随机读写的速度:顺序写入VS随机写入
图为常规硬盘或SSD读取的顺序写入甚至超过了随机存储器的读取和写入。当然,与顺序内存读写相比还是有很大的差距。
所以Kafka选择顺序读写磁盘也就不足为奇了。
下面我们以传统机械盘为例,详细演示一下顺序读写和随机读写的含义。
盘片和**磁盘区域:**硬盘驱动器上通常有多个磁盘。板分为上侧和下侧。有效侧面称为板面。一般来说,上下两边都有效,即:磁盘数量=磁盘数量*2。
磁头:当磁头改变车道读写数据时,通过机械装置实现,速度一般较慢;而磁头则通过电子设备切换磁盘表面来读写数据,速度通常较高,因此磁头通常在读写柱面后开始搜索(无需切换磁道),因此磁盘读写效率更快。 传统机械轮
轨道:轨道是以中心轴为中心的圆环。圆盘的表面有多个带,带之间有间隙。磁道是磁盘存储数据的介质。磁道上有一层磁性数据载体,磁头可以将磁性数据载体的极性转换成数据信号,即磁盘读取和磁盘写入正好相反。
圆柱:圆盘由不同圆盘表面上相同半径的条带组成,即圆柱体总数=某个圆盘表面上的条带数。
扇区:单个磁道由若干个弧形扇区组成,盘片上每个磁道的扇区数相同。扇区是最小的存储单位,常见扇区大小为 512 字节。单盘图
如果系统一次只读取一个扇区,效率会太低,于是就出现了块的概念。文件读取的最小单位是块。根据操作系统的不同,一个块通常由多个扇区组成。
有了磁盘的背景知识,我们就很容易理解顺序读写以及随机读写。
插入维基百科定义:顺序读写:这是一种按照记录的逻辑顺序执行读写操作的访问方法,即按照信息在内存中的实际位置确定的顺序使用信息。随机读写:是指在内存中读取或写入一条消息时,所需的时间与该信息的位置无关。
读取第一个块时,读取块数据必须经过三个步骤:搜索、旋转延迟、传输。至于下一个块,如果它在磁盘上的其他任何位置,则在读取该块的数据之前,它的访问也会经过寻道、旋转、延迟和传输。我们称这种方法为随机读写。但是,如果该块的起始扇区恰好位于刚刚到达的块后面,则磁头可以立即遇到它,而无需等待直接传输。这就是所谓的顺序读写。
好,我们回到Kafka身上,详细解释一下Kafka是如何实现数据的顺序读写的。
Kafka顺序写入数据。以下所有分区均被视为文件。收到每个新数据后,Kafka都会将数据插入到文件末尾。虚线方块表示文件末尾。 顺序写入
这种方法的一个问题是删除数据不方便,所以Kafka通常会保留所有数据。每个消费者对于需要捕获的每个主题都有一个偏移量。读取进度或坐标。顺序读取
内存映射文件(MMAP)
在文章开头我们看到了顺序读取和写入硬盘基本上对应内存的随机读写速度差不多,但是对于内存的顺序读写还是太慢了。如果Kafka想进一步提高效率怎么办?可以利用现代操作系统的分页存储来充分利用为了提高效率,这也是下面要介绍的MMAP技术。
MMAP也就是内存映射文件。64位操作系统,通常可以代表一个20G的数据文件,它的工作原理是直接利用操作系统页面将文件直接映射到物理内存上,映射完成后会对物理内存上的操作同步到硬盘上进行读写。读写内存(逻辑内存)时,不必担心内存的大小,因为有虚拟内存覆盖它。这种方法提供了很大的 I/O 改进,并节省了从用户空间复制到内核空间的成本。
还有一个明显的错误是写入MMAP的数据实际上并没有写入硬盘。操作系统只有在程序主动调用flush时才将数据写入硬盘。
Kafka补充了一个参数: Producer.type ,可以用来控制是否进行主动冲洗。如果Kafka写入MMAP,它会立即被刷新,然后返回到Producer,这称为同步;写入mmap后,立即返回到Producer,无需调用flush,这就是async。
零复制
Kafka的另一个黑技就是零复制的运用。如果想深入了解零拷贝,就需要知道什么是DMA。
什么是DMA?
我们都知道CPU速度与磁盘IO速度相比,相差几个数量级。你可以用乌龟和火箭来比喻。
一般情况下,IO操作都是由CPU发出,然后等待IO设备完成操作并返回。那么CPU就会花费大量的时间等待IO操作。
但等待CPU在很多情况下并没有太大的实际意义。我们在 I/O 设备上执行的许多操作实际上只是将内存中的数据传输到 I/O 设备。例如,当复制大文件时,如果所有数据都必须经过CPU,那将是浪费时间。
基于此,就有了DMA技术,翻译过来就是直接内存访问。这样可以减少CPU的等待时间。
Kafka零拷贝原理
如果我们不使用零拷贝技术,消费者会消费Kafka的数据,Kafka会从磁盘读取数据并发送给网络。总共发生四个数据传输过程。其中两个是 DMA 传输,另外两个是 CPU 控制的传输。 四个传输过程
第一次传输 :从硬盘读取数据到操作系统内核的缓冲区中。此传输通过 DMA 完成。
第二次传输:将内核缓冲区中的数据复制到保留内存中。该传输由 CPU 处理。
第三次传输:从分配的内存写入操作系统的Socket缓冲区。该传输由 CPU 处理。
第四次传输:从Socket缓冲区写入网卡缓冲区。此传输通过 DMA 完成。
Kafka 中实际上只有两次数据传输,如下图: 两次传输,零拷贝技术
第一次传输 :通过 DMA 直接从硬盘读取到操作系统内核内的读缓冲区。
第二次广播:根据Socket描述符信息,直接从读缓冲区写入网卡缓冲区。
可以看到相同数据的传输次数从4次变成了2次,并且没有数据通过CPU传输。所有数据均通过 DMA 传输。内存层面没有副本(copy)。这种方法称为零复制。
无论传输的数据量有多大,使用零副本传输相同的数据可以减少65%的时间,大大提高了机器数据传输的传输速度。这也是Kafka能够支撑百万TPS的重要原因。
批量数据(批量处理)
当消费者(消费者)需要消费数据时,首先想到的是消费者需要一个,kafka发送一个,消费者发送另一个,kafka发送另一个。但Kafka实际上并没有这么做。Kafka只是聪明而已。
Kafka将所有消息单独存储在文件中。当消费者需要数据时,Kafka将文件直接发送给消费者。例如,如果一个文件包含 100 万条消息,则数据量可能为 1000 万条。如果消费者和Kafka之间的网络良好,大约1秒就可以发送10MB。在 100 万 TPS 的情况下,Kafka每秒可以处理 10 万条消息。信息。
看完这篇,你可能会有疑问。消费者只需要一条消息。卡夫卡发送了整个文件。如何处理文件中的其余消息?不要忘记,消费者可以通过offset来记录消费进度。
发送文件的另一个好处是可以捆绑文件,减少网络IO损失。
总结
最后总结一下Kafka百万级TPS支撑的秘诀:
(1)依次输入数据,追加到分区末尾,这样速度就最佳的。
(2)利用MMAP技术映射磁盘文件和内存,Kafka可以将内存当做磁盘来管理。
(3)通过DMA技术可以实现零拷贝,减少数据传输次数。
(4)读取数据时配合sendfile直接强制输出。批量压缩将所有消息转换为批处理文件,合理减少网络IO损失。
作者:笑的建筑师
链接:https://juejin.cn/post/6896856225862909960
来源:掘金版权商业转载请联系作者授权。非商业转载请注明来源。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网