起源:cnblogs.com/starluke/p/12558952.html

Kafka是大数据畛域无处不在的消息中间件,目前宽泛应用在企业外部的实时数据管道,并帮忙企业构建本人的流计算应用程序。

Kafka尽管是基于磁盘做的数据存储,但却具备高性能、高吞吐、低延时的特点,其吞吐量动辄几万、几十上百万。

然而很多应用过Kafka的人,常常会被问到这样一个问题,Kafka为什么速度快,吞吐量大;大部分被问的人都是一下子就懵了,或者是只晓得一些简略的点,本文就简略的介绍一下Kafka为什么吞吐量大,速度快。

另外,最近面试整顿了 Java 最新、最全的面试题:

https://www.javastack.cn/mst/

一、程序读写

家喻户晓Kafka是将音讯记录长久化到本地磁盘中的,个别人会认为磁盘读写性能差,可能会对Kafka性能如何保障提出质疑。实际上不论是内存还是磁盘,快或慢关键在于寻址的形式,磁盘分为程序读写与随机读写,内存也一样分为程序读写与随机读写。基于磁盘的随机读写的确很慢,但磁盘的程序读写性能却很高,一般而言要高出磁盘随机读写三个数量级,一些状况下磁盘程序读写性能甚至要高于内存随机读写。

这里给出驰名学术期刊 ACM Queue 上的性能比照图:

磁盘的程序读写是磁盘应用模式中最有法则的,并且操作系统也对这种模式做了大量优化,Kafka就是应用了磁盘程序读写来晋升的性能。Kafka的message是一直追加到本地磁盘文件开端的,而不是随机的写入,这使得Kafka写入吞吐量失去了显著晋升 。

上图就展现了Kafka是如何写入数据的, 每一个Partition其实都是一个文件 ,收到音讯后Kafka会把数据插入到文件开端(虚框局部)。

这种办法有一个缺点—— 没有方法删除数据 ,所以Kafka是不会删除数据的,它会把所有的数据都保留下来,每个消费者(Consumer)对每个Topic都有一个offset用来示意 读取到了第几条数据 。

两个消费者,Consumer1有两个offset别离对应Partition0、Partition1(假如每一个Topic一个Partition);Consumer2有一个offset对应Partition2。这个offset是由客户端SDK负责保留的,Kafka的Broker齐全忽视这个货色的存在;个别状况下SDK会把它保留到zookeeper外面。(所以须要给Consumer提供zookeeper的地址)。

如果不删除硬盘必定会被撑满,所以Kakfa提供了两种策略来删除数据。一是基于工夫,二是基于partition文件大小。具体配置能够参看它的配置文档。

二、Page Cache

为了优化读写性能,Kafka利用了操作系统自身的Page Cache,就是利用操作系统本身的内存而不是JVM空间内存。这样做的益处有:

  • 防止Object耗费:如果是应用 Java 堆,Java对象的内存耗费比拟大,通常是所存储数据的两倍甚至更多。
  • 防止GC问题:随着JVM中数据一直增多,垃圾回收将会变得复杂与迟缓,应用零碎缓存就不会存在GC问题

相比于应用JVM或in-memory cache等数据结构,利用操作系统的Page Cache更加简略牢靠。

首先,操作系统层面的缓存利用率会更高,因为存储的都是紧凑的字节构造而不是独立的对象。

其次,操作系统自身也对于Page Cache做了大量优化,提供了 write-behind、read-ahead以及flush等多种机制。

再者,即便服务过程重启,零碎缓存仍然不会隐没,防止了in-process cache重建缓存的过程。

通过操作系统的Page Cache,Kafka的读写操作基本上是基于内存的,读写速度失去了极大的晋升。

三、零拷贝

linux操作系统 “零拷贝” 机制应用了sendfile办法, 容许操作系统将数据从Page Cache 间接发送到网络,只须要最初一步的copy操作将数据复制到 NIC 缓冲区, 这样防止从新复制数据 。示意图如下:

通过这种 “零拷贝” 的机制,Page Cache 联合 sendfile 办法,Kafka生产端的性能也大幅晋升。这也是为什么有时候生产端在一直生产数据时,咱们并没有看到磁盘io比拟高,此刻正是操作系统缓存在提供数据。

当Kafka客户端从服务器读取数据时,如果不应用零拷贝技术,那么大抵须要经验这样的一个过程:

  1. 操作系统将数据从磁盘上读入到内核空间的读缓冲区中。
  2. 应用程序(也就是Kafka)从内核空间的读缓冲区将数据拷贝到用户空间的缓冲区中。
  3. 应用程序将数据从用户空间的缓冲区再写回到内核空间的socket缓冲区中。
  4. 操作系统将socket缓冲区中的数据拷贝到NIC缓冲区中,而后通过网络发送给客户端。

从图中能够看到,数据在内核空间和用户空间之间穿梭了两次,那么是否防止这个多余的过程呢?当然能够,Kafka应用了零拷贝技术,也就是间接将数据从内核空间的读缓冲区间接拷贝到内核空间的socket缓冲区,而后再写入到NIC缓冲区,防止了在内核空间和用户空间之间穿梭。

可见,这里的零拷贝并非指一次拷贝都没有,而是防止了在内核空间和用户空间之间的拷贝。如果真是一次拷贝都没有,那么数据发给客户端就没了不是?不过,光是省下了这一步就能够带来性能上的极大晋升。

四、分区分段+索引

Kafka的message是按topic分类存储的,topic中的数据又是依照一个一个的partition即分区存储到不同broker节点。每个partition对应了操作系统上的一个文件夹,partition实际上又是依照segment分段存储的。这也十分合乎分布式系统分辨别桶的设计思维。

通过这种分区分段的设计,Kafka的message音讯实际上是分布式存储在一个一个小的segment中的,每次文件操作也是间接操作的segment。为了进一步的查问优化,Kafka又默认为分段后的数据文件建设了索引文件,就是文件系统上的.index文件。这种分区分段+索引的设计,不仅晋升了数据读取的效率,同时也进步了数据操作的并行度。

五、批量读写

Kafka数据读写也是批量的而不是单条的。

除了利用底层的技术外,Kafka还在应用程序层面提供了一些伎俩来晋升性能。最显著的就是应用批次。在向Kafka写入数据时,能够启用批次写入,这样能够防止在网络上频繁传输单个音讯带来的提早和带宽开销。假如网络带宽为10MB/S,一次性传输10MB的音讯比传输1KB的音讯10000万次显然要快得多。

六、批量压缩

在很多状况下,零碎的瓶颈不是CPU或磁盘,而是网络IO,对于须要在广域网上的数据中心之间发送音讯的数据流水线尤其如此。进行数据压缩会耗费大量的CPU资源,不过对于kafka而言,网络IO更应该须要思考。

  1. 如果每个音讯都压缩,然而压缩率绝对很低,所以Kafka应用了批量压缩,行将多个音讯一起压缩而不是单个消息压缩
  2. Kafka容许应用递归的音讯汇合,批量的音讯能够通过压缩的模式传输并且在日志中也能够放弃压缩格局,直到被消费者解压缩
  3. Kafka反对多种压缩协定,包含Gzip和Snappy压缩协定

Kafka速度的秘诀在于,它把所有的音讯都变成一个批量的文件,并且进行正当的批量压缩,缩小网络IO损耗,通过mmap进步I/O速度,写入数据的时候因为单个Partion是开端增加所以速度最优;读取数据的时候配合sendfile间接暴力输入。

近期热文举荐:

1.1,000+ 道 Java面试题及答案整顿(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!