支持百万级TPS,Kafka是怎么作到的?答案藏在这10张图里

本文 github/JavaMap 已收录,有Java程序员进阶技术知识地图以及个人系列文章,欢迎你们Star。java

谈到大数据传输都会想到 Kafka,Kafka 号称大数据的杀手锏,在业界有不少成熟的应用场景而且被主流公司承认。这款为大数据而生的消息中间件,以其百万级TPS的吞吐量名声大噪,迅速成为大数据领域的宠儿,在数据采集、传输、存储的过程当中发挥着举足轻重的做用。git

在业界已经有不少成熟的消息中间件如:RabbitMQ, RocketMQ, ActiveMQ, ZeroMQ,为何 Kafka 在众多的敌手中依然能有一席之地,固然靠的是其强悍的吞吐量。下面带领你们来揭秘。程序员

Kafka 如何作到支持百万级 TPS ?

先用一张思惟导图直接告诉你答案:github

Kafka支持百万TPS的秘密
Kafka支持百万TPS的秘密

顺序读写磁盘

生产者写入数据和消费者读取数据都是顺序读写的,先来一张图直观感觉一下顺序读写和随机读写的速度:面试

顺序写 VS 随机写
顺序写 VS 随机写

从图中能够看出传统硬盘或者SSD的顺序读写甚至超过了内存的随机读写,固然与内存的顺序读写对比差距仍是很大。微信

因此Kafka选择顺序读写磁盘也不足为奇了。markdown

下面以传统机械磁盘为例详细介绍一下什么是顺序读写和随机读写。网络

盘片和**盘面:**一块硬盘通常有多块盘片,盘片分为上下两面,其中有效面称为盘面,通常上下都有效,也就是说:盘面数 = 盘片数 * 2。架构

磁头:磁头切换磁道读写数据时是经过机械设备实现的,通常速度较慢;而磁头切换盘面读写数据是经过电子设备实现的,通常速度较快,所以磁头通常是先读写完柱面后才开始寻道的(不用切换磁道),这样磁盘读写效率更快。app

传统机械磁盘
传统机械磁盘

磁道:磁道就是以中间轴为圆心的圆环,一个盘面有多个磁道,磁道之间有间隙,磁道也就是磁盘存储数据的介质。磁道上布有一层磁介质,经过磁头可使磁介质的极性转换为数据信号,即磁盘的读,磁盘写恰好与之相反。

柱面:磁盘中不一样盘面中半径相同的磁道组成的,也就是说柱面总数 = 某个盘面的磁道数。

扇区:单个磁道就是多个弧形扇区组成的,盘面上的每一个磁道拥有的扇区数量是相等。扇区是最小存储单元,通常扇区大小为512bytes。

单盘示意图
单盘示意图

若是系统每次只读取一个扇区,那恐怕效率过低了,因此出现了block(块)的概念。文件读取的最小单位是block,根据不一样操做系统一个block通常由多个扇区组成。

有了磁盘的背景知识咱们就能够很容易理解顺序读写和随机读写了。

插播维基百科定义: 顺序读写:是一种按记录的逻辑顺序进行读、写操做的存取方法 ,即按照信息在存储器中的实际位置所决定的顺序使用信息。 随机读写:指的是当存储器中的消息被读取或写入时,所须要的时间与这段信息所在的位置无关。

当读取第一个block时,要经历寻道、旋转延迟、传输三个步骤才能读取完这个block的数据。而对于下一个block,若是它在磁盘的其余任意位置,访问它会一样经历寻道、旋转、延时、传输才能读取完这个block的数据,咱们把这种方式叫作随机读写。可是若是这个block的起始扇区恰好在刚才访问的block的后面,磁头就能马上遇到,不需等待直接传输,这种就叫顺序读写

好,咱们再回到 Kafka,详细介绍Kafka如何实现顺序读写入数据。

Kafka 写入数据是顺序的,下面每个Partition 均可以当作一个文件,每次接收到新数据后Kafka会把数据插入到文件末尾,虚框部分表明文件尾。

顺序写
顺序写

这种方法有一个问题就是删除数据不方便,因此 Kafka 通常会把全部的数据都保留下来,每一个消费者(Consumer)对每一个Topic都有一个 offset 用来记录读取进度或者叫坐标。

顺序读
顺序读

Memory Mapped Files(MMAP)

在文章开头咱们看到硬盘的顺序读写基本能与内存随机读写速度媲美,可是与内存顺序读写相比仍是太慢了,那 Kafka 若是有追求想进一步提高效率怎么办?可使用现代操做系统分页存储来充分利用内存提升I/O效率,这也是下面要介绍的 MMAP 技术。

MMAP也就是内存映射文件,在64位操做系统中通常能够表示 20G 的数据文件,它的工做原理是直接利用操做系统的 Page 来实现文件到物理内存的直接映射,完成映射以后对物理内存的操做会被同步到硬盘上。

MMAP原理
MMAP原理

经过MMAP技术进程能够像读写硬盘同样读写内存(逻辑内存),没必要关心内存的大小,由于有虚拟内存兜底。这种方式能够获取很大的I/O提高,省去了用户空间到内核空间复制的开销。

也有一个很明显的缺陷,写到MMAP中的数据并无被真正的写到硬盘,操做系统会在程序主动调用 flush 的时候才把数据真正的写到硬盘。

Kafka提供了一个参数:producer.type 来控制是否是主动 flush,若是Kafka写入到MMAP以后就当即flush而后再返回Producer叫同步(sync);写入MMAP以后当即返回Producer不调用flush叫异步(async)。

Zero Copy(零拷贝)

Kafka 另一个黑技术就是使用了零拷贝,要想深入理解零拷贝必须得知道什么是DMA。

什么是DMA?

众所周知 CPU 的速度与磁盘 IO 的速度比起来相差几个数量级,能够用乌龟和火箭作比喻。

通常来讲 IO 操做都是由 CPU 发出指令,而后等待 IO 设备完成操做后返回,那CPU会有大量的时间都在等待IO操做。

可是CPU 的等待在不少时候并无太多的实际意义,咱们对于 I/O 设备的大量操做其实都只是把内存里面的数据传输到 I/O 设备而已。好比进行大文件复制,若是全部数据都要通过 CPU,实在是有点儿太浪费时间了。

基于此就有了DMA技术,翻译过来也就是直接内存访问(Direct Memory Access),有了这个能够减小 CPU 的等待时间。

Kafka 零拷贝原理

若是不使用零拷贝技术,消费者(consumer)从Kafka消费数据,Kafka从磁盘读数据而后发送到网络上去,数据一共发生了四次传输的过程。其中两次是 DMA 的传输,另外两次,则是经过 CPU 控制的传输。

四次传输过程
四次传输过程

第一次传输:从硬盘上将数据读到操做系统内核的缓冲区里,这个传输是经过 DMA 搬运的。

第二次传输:从内核缓冲区里面的数据复制到分配的内存里面,这个传输是经过 CPU 搬运的。

第三次传输:从分配的内存里面再写到操做系统的 Socket 的缓冲区里面去,这个传输是由 CPU 搬运的。

第四次传输:从 Socket 的缓冲区里面写到网卡的缓冲区里面去,这个传输是经过 DMA 搬运的。

实际上在kafka中只进行了两次数据传输,以下图:

两次传输,零拷贝技术
两次传输,零拷贝技术

第一次传输:经过 DMA从硬盘直接读到操做系统内核的读缓冲区里面。

第二次传输:根据 Socket 的描述符信息直接从读缓冲区里面写入到网卡的缓冲区里面。

咱们能够看到同一份数据的传输次数从四次变成了两次,而且没有经过 CPU 来进行数据搬运,全部的数据都是经过 DMA 来进行传输的。没有在内存层面去复制(Copy)数据,这个方法称之为零拷贝(Zero-Copy)。

不管传输数据量的大小,传输一样的数据使用了零拷贝可以缩短 65% 的时间,大幅度提高了机器传输数据的吞吐量,这也是Kafka可以支持百万TPS的一个重要缘由。

Batch Data(数据批量处理)

当消费者(consumer)须要消费数据时,首先想到的是消费者须要一条,kafka发送一条,消费者再要一条kafka再发送一条。但实际上 Kafka 不是这样作的,Kafka 耍小聪明了。

Kafka 把全部的消息都存放在一个一个的文件中,当消费者须要数据的时候 Kafka 直接把文件发送给消费者。好比说100万条消息放在一个文件中多是10M的数据量,若是消费者和Kafka之间网络良好,10MB大概1秒就能发送完,既100万TPS,Kafka每秒处理了10万条消息。

看到这里你能够有疑问了,消费者只须要一条消息啊,kafka把整个文件都发送过来了,文件里面剩余的消息怎么办?不要忘了消费者能够经过offset记录消费进度。

发送文件还有一个好处就是能够对文件进行批量压缩,减小网络IO损耗。

总结

最后再总结一下 Kafka 支持百万级 TPS 的秘密:

(1)顺序写入数据,在 Partition 末尾追加,因此速度最优。

(2)使用 MMAP 技术将磁盘文件与内存映射,Kafka 能够像操做磁盘同样操做内存。

(3)经过 DMA 技术实现零拷贝,减小数据传输次数。

(4)读取数据时配合sendfile直接暴力输出,批量压缩把全部消息变成一个批量文件,合理减小网络IO损耗。

-- END --

平常厚脸皮求赞:你好技术人,先赞后看养成习惯,你的赞对于我很是重要。

做者简介:

☕读过几年书:华中科技大学硕士毕业;

😂浪过几个大厂:华为、网易、百度……

😘一直坚信技术能改变生活,愿保持初心,加油技术人!

微信搜索公众号【爱笑的架构师】,关注这个对技术和生活有追求的技术人。

文章持续更新,在 github/JavaMap 中能够看到我归档的系列文章,有面试经验和技术干货,欢迎Star。

相关文章
相关标签/搜索