这篇文章来聊一下 Kafka 的一些架构设计原理,这也是互联网公司面试时很是高频的技术考点。java
Kafka 是高吞吐低延迟的高并发、高性能的消息中间件,在大数据领域有极为普遍的运用。配置良好的 Kafka 集群甚至能够作到每秒几十万、上百万的超高并发写入。python
那么 Kafka 究竟是如何作到这么高的吞吐量和性能的呢?这篇文章咱们来详细说一下。linux
首先 Kafka 每次接收到数据都会往磁盘上去写,以下图所示:web
那么在这里咱们不由有一个疑问了,若是把数据基于磁盘来存储,频繁的往磁盘文件里写数据,这个性能会不会不好?你们确定都以为磁盘写性能是极差的。
面试
没错,要是真的跟上面那个图那么简单的话,那确实这个性能是比较差的。缓存
可是实际上 Kafka 在这里有极为优秀和出色的设计,就是为了保证数据写入性能,首先 Kafka 是基于操做系统的页缓存来实现文件写入的。性能优化
操做系统自己有一层缓存,叫作 Page Cache,是在内存里的缓存,咱们也能够称之为 OS Cache,意思就是操做系统本身管理的缓存。对大数据以及人工智能概念都是模糊不清的,该按照什么线路去学习,学完往哪方面发展,想深刻了解,想学习的同窗欢迎加入大数据学习扣群:数据515—269+数字485,有大量干货(零基础以及进阶的经典实战)分享给你们,而且有清华大学毕业的资深大数据讲师给你们免费授课,给你们分享目前国内最完整的大数据高端实战实用学习流程体系 。从java和linux入手,其后逐步的深刻到HADOOP-hive-oozie-web-flume-python-hbase-kafka-scala-SPARK等相关知识一一分享!架构
你在写入磁盘文件的时候,能够直接写入这个 OS Cache 里,也就是仅仅写入内存中,接下来由操做系统本身决定何时把 OS Cache 里的数据真的刷入磁盘文件中。并发
仅仅这一个步骤,就能够将磁盘文件写性能提高不少了,由于其实这里至关因而在写内存,不是在写磁盘,你们看下图:分布式
接着另一个就是 kafka 写数据的时候,很是关键的一点,它是以磁盘顺序写的方式来写的。
也就是说,仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。
普通的机械磁盘若是你要是随机写的话,确实性能极差,也就是随便找到文件的某个位置来写数据。
可是若是你是追加文件末尾按照顺序的方式来写数据的话,那么这种磁盘顺序写的性能基本上能够跟写内存的性能自己也是差很少的。
因此你们就知道了,上面那个图里,Kafka 在写数据的时候,一方面基于 OS 层面的 Page Cache 来写数据,因此性能很高,本质就是在写内存罢了。
另一个,它是采用磁盘顺序写的方式,因此即便数据刷入磁盘的时候,性能也是极高的,也跟写内存是差很少的。
基于上面两点,Kafka 就实现了写入数据的超高性能。那么你们想一想,假如说 Kafka 写入一条数据要耗费 1 毫秒的时间,那么是否是每秒就是能够写入 1000 条数据?
可是假如 Kafka 的性能极高,写入一条数据仅仅耗费 0.01 毫秒呢?那么每秒是否是就能够写入 10 万条数据?
因此要保证每秒写入几万甚至几十万条数据的核心点,就是尽最大可能提高每条数据写入的性能,这样就能够在单位时间内写入更多的数据量,提高吞吐量。
说完了写入这块,再来谈谈消费这块。
你们应该都知道,从 Kafka 里咱们常常要消费数据,那么消费的时候实际上就是要从 Kafka 的磁盘文件里读取某条数据而后发送给下游的消费者,以下图所示:
那么这里若是频繁的从磁盘读数据而后发给消费者,性能瓶颈在哪里呢?
假设要是 Kafka 什么优化都不作,就是很简单的从磁盘读数据发送给下游的消费者,那么大概过程以下所示:
先看看要读的数据在不在 OS Cache 里,若是不在的话就从磁盘文件里读取数据后放入 OS Cache。
接着从操做系统的 OS Cache 里拷贝数据到应用程序进程的缓存里,再从应用程序进程的缓存里拷贝数据到操做系统层面的 Socket 缓存里。
最后从 Socket 缓存里提取数据后发送到网卡,最后发送出去给下游消费。
整个过程,以下图所示:
你们看上图,很明显能够看到有两次不必的拷贝吧!一次是从操做系统的 Cache 里拷贝到应用进程的缓存里,接着又从应用程序缓存里拷贝回操做系统的 Socket 缓存里。
并且为了进行这两次拷贝,中间还发生了好几回上下文切换,一下子是应用程序在执行,一下子上下文切换到操做系统来执行。
因此这种方式来读取数据是比较消耗性能的。Kafka 为了解决这个问题,在读数据的时候是引入零拷贝技术。
也就是说,直接让操做系统的 Cache 中的数据发送到网卡后传输给下游的消费者,中间跳过了两次拷贝数据的步骤,Socket 缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到 Socket 缓存。
你们看下图,体会一下这个精妙的过程:
经过零拷贝技术,就不须要把 OS Cache 里的数据拷贝到应用缓存,再从应用缓存拷贝到 Socket 缓存了,两次拷贝都省略了,因此叫作零拷贝。
对 Socket 缓存仅仅就是拷贝数据的描述符过去,而后数据就直接从 OS Cache 中发送到网卡上去了,这个过程大大的提高了数据消费时读取文件数据的性能。
并且你们会注意到,在从磁盘读数据的时候,会先看看 OS Cache 内存中是否有,若是有的话,其实读数据都是直接读内存的。
若是 Kafka 集群通过良好的调优,你们会发现大量的数据都是直接写入 OS Cache 中,而后读数据的时候也是从 OS Cache 中读。
至关因而 Kafka 彻底基于内存提供数据的写和读了,因此这个总体性能会极其的高。
说个题外话,下回有机会给你们说一下 Elasticsearch 的架构原理,其实 ES 底层也是大量基于 OS Cache 实现了海量数据的高性能检索的,跟 Kafka 原理相似。
经过这篇文章对 Kafka 底层的页缓存技术的使用,磁盘顺序写的思路,以及零拷贝技术的运用,你们应该就明白 Kafka 每台机器在底层对数据进行写和读的时候采起的是什么样的思路,为何它的性能能够那么高,作到每秒几十万的吞吐量。
这种设计思想对咱们平时本身设计中间件的架构,或者是出去面试的时候,都有很大的帮助。
看到最后的都是真爱了,感受文章不错的记得给小编点个赞哦,关注小编,之后会有更多的精品文章输出哦。
给你们推荐一个架构技术交流群:714827309 ,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析 ,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,相信对于已经工做 和遇到技术瓶颈的码友,在这个群里会有你须要的内容。 点击连接加入群聊【JAVA高级架构技术交流】:jq.qq.com/?_wv=1027&a…