技术大佬问我,kafka为什么这么的快?

技术大佬 : 佩琪看你一脸的闷闷不乐,最近的面试又闹心了?

佩琪: 哎,大佬,别提了,伤心。关于消息中间件的面试题:比如 kafka消息防丢防重防乱序 的8股文,我都回答的很丝滑,我感觉回答完 整个人都快飘起来了;谁知 面试官微微一笑,突然问我:为什么kafka这么快?

技术大佬 : 哦,那你怎么回答的呢?

佩琪: 我当时立刻 条件般联想到 8股文,回答到:因为 kafka使用了顺序写磁盘文件;还有零拷贝;还有它是一个分布式消息队列。

技术大佬 : 哦,那你回答的还挺"标准"的呀。

佩琪: 谁说不是呢,然后面试官又问我,能详细说说你对他们的理解吗?

技术大佬 : 哦,那你怎么回答的了?

佩琪: 听完这个问题 我当时内心就慌了,我平常就是个crud boy;时间和精力都用于 和产品battle和写crud去了,哪还有时间去深挖这些"高端东西";我很低下的回答到:"尊敬的面试官,不好意思,我不太理解这里面的细节"

技术大佬 : 哦,然后了?

佩琪: 然后面试官,让我回家等通知,然后就没有然后了。。。。。。

佩琪: 大佬,大家都说kafka这么快的原因是上面那三个主要原因;真的是这三个主要原因吗?

技术大佬 : 额,这个嘛,主流说法是这三个。不过从官方源码和kafka官方设计文档上来说,kafka这么快,可以从生产端,broker端,和消费端去回答和理解。

佩琪: 哦,这怎么理解了???

技术大佬 : 从这三个维度分析:
生产端: 主要使用了,异步提交批量发送
broker端 : 分布式特性,指通过扩展机器来提升发送和消费速度。存储消息,主要是用了同步写磁盘缓存 +异步顺序刷数据到磁盘 进行写 性能的提升;获取消息时 使用了零拷贝技术 进行读性能提升;
消费者端: 使用了批量主动拉取方式;

另外从网络层上说,kafka从生产端到broker端,进行了批量消息压缩,减轻了数据传输包大小,降低了网络负载。

佩琪: (心理嘀咕:丢,你是不是在装B,kafak这么快真的有这么多原因)哦哦,请问这个生产端 异步提交,批量发送 是啥意思?

技术大佬 : 异步提交:主要是指我们应用 调用 kafka send接口 发送消息是个异步接口。 这个接口,底层其实是没有把消息发给broker端,它把消息直接写入内存里,然后就返回了;所以说他是一个异步写消息接口,并且上层看起来还很快;因为这个接口它不需要经过网络通信,broker端进行存储,然后应答给发送端 这个过程。它直接写消息数据到本地内存,当然很快了。

佩琪: (摸了摸猪头) 哦哦,大概明白了,这就和我们日常使用的线程池 提交任务一样,调用方只管提交任务,而不用管任务是否执行,这样上层业务执行起来很快,因为无阻塞。那这个批量发送,又是什么意思了?

技术大佬 : 可以看看下面这个图

前面说了,发送消息接口是个异步接口,消息都暂存在内存里;kafka 生产端 还会有一个专门的IO send线程:把内存中的消息,按照消息路由算法,把发往相同broker的消息,聚合到一个消息集合里,作为一个消息集的数据包 发送给对应的broker

佩琪: 有点抽象了,能简化下吗?

技术大佬 : 嗯,如果不用批量发送,那么一条消息,就是一次网络IO;用了批量发送,即把多条消息聚合为一条消息集,然后发送给broker;比如10条消息,打包成消息集,底层一次网络IO,就发给broker端了;批量发送能提高性能,是因为 它减少网络往返的IO次数和开销,达到了性能的提升。

技术大佬: 其实生产端还用了很多提升性能的技术,有兴趣你可以去看看这个《读kafka生产端源码,窥kafka设计之道(上)》

佩琪: 哦哦。大佬,请问这个 broker端的分布式特性,是啥意思了?

技术大佬 : 这个主要是指:broker 的topic 分区,可以通过增加机器方式来增加topic 的分区数; 比如以前生产端只能往3台机器的3个分区上发消息;现在broker扩了2台机器,topic 增加到了5个分区;这样生产端就能往5台机器的5个分区上发消息;这样消息就被另外增加的2台机器进行了分担存储和处理;以此完成了,增加机器即 增加消息的处理性能和存储空间。如下图所示

佩琪: 哦哦,那数据落盘优化又是什么了?

技术大佬 : 这里的数据落盘优化,主要是指broker端 接受到消息后,是需要写消息到磁盘上的文件系统里的;这里的写,使用了 同步写数据到磁盘缓存;然后异步 顺序 刷数据 到磁盘。如下图所示,

从这里可看出kafka写数据到文件系统的主流程,其实是写入到page cache里,类似与往内存中写数据,所以主流程是很快的,差不多要 100纳秒 ;然后涉及到刷新数据到磁盘,其实是要把数据写入到磁盘的,那这个速度就很慢了,差不多要毫秒级别;两者相差了1个数量级。所以刷新数据到磁盘这种比较慢的操作,采用了异步,以减少对数据写入这个主流程的延迟。

但kafka在刷数据到磁盘这个比较慢的动作里,也还是做了优化的,他用顺序追加文件内容的方式,而不是随机写文件内容的方式,其实是为了 减少 底层硬盘磁头随机定位的次数,以此来提高刷数据到磁盘的速度。

技术大佬 : 这块更多的详情可以看看这个《为什么kafka使用磁盘文件来缓存和存储消息

佩琪: 哦哦,那这个零拷贝技术又是个什么呢?

技术大佬 : 这里所谓的零拷贝,不是不拷贝。是指broker 减少了 从磁盘读消息 到 通过网络发送给消费者,这一过程中的 数据拷贝次数。传统的不使用零拷贝 需要的4次数据复制,4次系统调用;使用零拷贝技术,只需要最多2次数据复制(或者一次数据复制)2次系统调用。入下图所示

传统意义下,不使用零拷贝,从磁盘读数据然后通过网络发送的过程

从这个过程我们可看到,

1 操作系统 将数据从磁盘copy 到内核空间的pagecache中

2 应用程序将数据从内核空间copy 到用户空间缓冲区

3 应用程序将数据copy 到内核空间的套接字缓冲区中

4 操作系统将数据从套接字缓冲区copy 到 NIC 缓冲区,并在其中通过网络发送

这显然效率很低下,因为数据集进行了4次copy 和4个系统调用。

kafka 使用send file方式:

从这个过程我们可看到,

1 操作系统 将数据从磁盘copy 到内核空间的pagecache中

2 操作系统 将数据从内核空间的pagecache copy 到 NIC 缓冲区,并在其中通过网络发送

而再结合前面讲的kafka采用同步写入pageche,异步刷新到磁盘的方式;很有可能broker在读取消息时,需要的消息已经在pageche中了,这又进一步减少了一次数据的复制;甚至很多时候,都不需要读取磁盘这个动作了,只需要把pagecache中的消息,copy到网络的NIC中这一次复制,就完成了一次消息的读取和发送。

技术大佬 : 这块更多的详情可以看看这个《通过零拷贝实现高效数据传输

佩琪:那这个消费端 批量拉取是什么意思了?

技术大佬 : 嗯嗯,这个......,是不是到点了,该干饭了,下午再聊?

佩琪: 丢,才11点半,你是不是不知道答案,随便找了个借口

总结

kafka 这么快的原因,主要为:

  1. 生产端:

    • 采用了异步提交消息的方式,加快了上层业务调用端的返回
    • 底层采用了 批量发送的方式,减少网络IO的次数。
  2. broker端

    • 写数据时,使用了同步写磁盘缓存+ 异步刷新数据到磁盘文件系统,提高了消息数据落到文件系统的速度;
    • 在读取消息时,使用零拷贝技术,减少磁盘IO读取次数,加快读消息过程
    • 利用broker天生的分布式能力,通过扩展硬件机器,带来消息发送和处理速度的提升。

原创不易,请 点赞,留言,关注,收藏 4暴击^^

参考资料:

kafka 官方文档: kafka.apache.org/documentati...

相关推荐
我叫啥都行41 分钟前
计算机基础知识复习9.7
运维·服务器·网络·笔记·后端
沛沛老爹1 小时前
服务监控插件全览:提升微服务可观测性的利器
微服务·云原生·架构·datadog·influx·graphite
无名指的等待7121 小时前
SpringBoot中使用ElasticSearch
java·spring boot·后端
.生产的驴2 小时前
SpringBoot 消息队列RabbitMQ 消费者确认机制 失败重试机制
java·spring boot·分布式·后端·rabbitmq·java-rabbitmq
huaqianzkh2 小时前
了解华为云容器引擎(Cloud Container Engine)
云原生·架构·华为云
AskHarries3 小时前
Spring Boot利用dag加速Spring beans初始化
java·spring boot·后端
Kika写代码3 小时前
【基于轻量型架构的WEB开发】【章节作业】
前端·oracle·架构
刘某某.3 小时前
使用OpenFeign在不同微服务之间传递用户信息时失败
java·微服务·架构
迪捷软件3 小时前
知识|智能网联汽车多域电子电气架构会如何发展?
架构·汽车
zyhJhon3 小时前
软考架构-层次架构风格
架构