kafka速度快的原因
2019/11/22 10:40:43

我们都知道Kafka非常快,比绝大多数的市场上其他消息中间件都要快。这里来研究下那么为什么Kafka那么快(当然不会是因为它用了Scala)。
Kafka的消息是保存或缓存在磁盘上的,一般认为在磁盘上读写数据是会降低性能的,因为寻址会比较消耗时间。
但是实际上,Kafka其中一个特性却是高吞吐率,即使是普通的服务器,Kafka也能轻松支持每秒百万级的写入请求,超过了大部分的消息中间件。这种特性使得Kafka在日志处理等海量数据场景中应用广泛。那么为什么Kafka速度那么快,可以从数据写入和数据读取两方面来分析。
Kafka的数据写入(生产者)
生产者(Producer)是负责向Kafka提交数据的,Kafka会把收到的消息都写入到磁盘中,因此可以认为它绝对不会丢失数据。
而为了优化写入速度,Kafka采用了两种技术,一种是顺序写入,一种是MMFile。
顺序写入
磁盘读写的快慢取决于你怎么使用它,一般可以分为顺序读写或者随机读写。
因为硬盘是机械结构,每次读写都会经过一个【寻址->写入】的过程,其中的寻址是一个十分耗时的机械动作,所以硬盘最讨厌随机I/O,最喜欢顺序I/O。为了提高读写硬盘的速度,Kafka就是使用的顺序I/O。而且Linux对于磁盘的读写优化也比较多,包括read-ahead、write-behind和磁盘缓存等。更多的,对Java的内存管理和垃圾回收会有优化,因为如果在内存做这些操作的时候,一个会导致Java对象的内存开销很大,另一个是随着堆内存数据的增多,Java的GC时间会变得很长。
因此可以总结出使用磁盘操作有以下几个好处:
1.磁盘顺序读写速度超过内存随机读写。
2.JVM的GC效率低,内存占用大,使用磁盘可以避免这一问题。
3.系统冷启动后,磁盘上的缓存依然可用(内存一旦关机数据就会清空,持久化到磁盘上则不会)。

上图就展示了Kafka是如何写入数据的,每一个Partition其实都是一个文件,收到消息后Kafka会把数据插入到文件的末尾(虚线框的部分)。
但是这种方法存在一个缺陷:没有办法删除数据。一次Kafka是不会删除数据的,它只会把所有的数据都保留下来,每个消费者(Consumer)对每个Topic都有一个offset用来表示读取到了第几条数据。

上图中有两个消费者,Consumer1有两个offset分别对应Partition0和Partition1(假设每一个Topic是一个Partition);Consumer2有一个offset对应Partition2.这个offset是由客户端SKD负责保存的,Kafka的Broker完全无视这个东西的存在;一般情况下SDK会把它保存到Zookeeper里面。(所以需要给Consumer提供Zookeeper的地址)。
如果数据完全不删除,那么肯定会导致硬盘爆满,所以Kafka提供了两种策略来删除数据,一是基于时间,二是基于Partition文件大小。具体配置可以参看它的配置文档。
MMFiles(Memory Mapped Files)
即便是顺序写入磁盘,磁盘的访问速度还是不可能追上内存的。所以Kafka的数据并不是实时的写入硬盘,它充分利用了现代操作系统的分页存储来利用内存,以此来提高I/O效率。Memory Mapped Files(后面简称MMAP)也被翻译成内存映射文件,在64位操作系统中一般可以表示20G的数据文件。它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。完成映射之后,你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。
通过MMAP,进程就可以像读写硬盘一样读写内存(当然是虚拟机内存),也不必关系内存的大小,因为有虚拟内存为我们兜底。使用这种方式可以获取很大的I/O提升,省去了用户空间到内核空间复制的开销(调用文件的read会有把数据先放到内核空间的内存中,然后再复制到用户空间的内存中)。但是这样也有一个很明显的缺陷:不可靠,因为写到MMAP中的数据并没有被真正地写入到硬盘中,操作系统会在程序主动调

下一页
返回列表
返回首页
©2019 Linux公社 - Linux系统门户网站 电脑版