kafka为什么那么快?

Kafka把所有消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络IO损耗。写数据的时候由于单个Partion是末尾添加所以速度最优,同时通过Memory Mapped Files提高I/O速度,读数据的时候使用sendfile提高效率。

kafka的消息是保存或缓存在磁盘上的,即使是普通的服务器,Kafka也可以轻松支持每秒百万级的写入请求,远超大部分的消息中间件。

为什么不适用内存存储?

kafka是由Scala和Java编写的,如果使用内存做存储的话虽然效率高,但是需要解决两个问题

1)JAVA对象的内存开销

2)java的gc

使用磁盘的话,可以很好的避免以上两点问题,在使用顺序读写的情况下保持可效率,同时解决了内存开销和gc问题,最重要的是一旦机器重启后不会丢失数据。

下面从读写两个方面分别分析下kafka为什么这么快

一、写数据

Kafka把收到的消息都写入到硬盘中(不会丢失数据),之所以能够提高kafka优化写入效率,kafka采取了以下几种方法。

顺序写入

因为硬盘是机械结构,每次读写都会寻址(最耗时)->写入,所以硬盘最讨厌随机I/O,最喜欢顺序I/O。为了提高读写硬盘的速度,Kafka就是使用顺序I/O。在顺序读写的情况下,某些优化场景磁盘的读写速度可以和内存持平。

对于kafka来说,每一个Partition其实都是一个文件 ,收到消息后Kafka会把数据插入到文件末尾。

不维护数据的状态

kafka不维护信息的状态,每个消费者(Consumer)对每个Topic都有一个offset用来表示读取到了第几条数据。

offset由客户端SDK负责保存,Kafka的Broker不关心offset的存在,一般情况下SDK会把它保存到zookeeper里面,所以调整zookeeper中的offset重新消费数据。

当然这种写入方式导致没法删除数据。

Memory Mapped Files

Kafka的数据并不是实时的写入硬盘 ,而是通过分页存储,利用内存提高I/O效率。

Memory Mapped Files(内存映射文件) ,它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。完成映射之后对物理内存的操作会在适当的时候被同步到硬盘上。使用这种方式可以获取很大的I/O提升, 省去了用户空间到内核空间复制的开销。

写到Memory Mapped Files中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用flush(参数producer.type)的时候才把数据真正的写到硬盘。

producer.type  async/sync 默认是sync 

当满足以下其中一个条件的时候就触发 发送

1)batch.num.messages 异步发送 每次批量发送的条目 

2)queue.buffering.max.ms 异步发送的时候 发送时间间隔 单位是毫秒

二、读数据

基于sendfile实现Zero Copy

对一个文件进行传输的时候,需要经过以下流程

1)调用read函数,文件数据被copy(1)到内核缓冲区

2)read函数返回后,文件数据会从内核缓冲区copy(2)到用户缓冲区

2)write函数调用,将文件数据从用户缓冲区copy(3)到内核与socket相关的缓冲区。

3)最后数据从socket缓冲区copy(4)到网卡。

可以看出流程中一共copy里四次

而sendfile系统调用则提供了一种不仅减少了数据复制,还减少了上下文切换的方法。Zero Copy直接从DMA的内核空间到Socket的内核空间,然后发送到网卡。

三、消息传输

在很多情况下,系统的瓶颈不是CPU或磁盘,而是网络IO。

Kafka把所有的消息都存放在一个一个的文件中,Kafka将多个消息一起压缩,当消费者需要数据的时候Kafka直接把“文件”发送给消费者。允许使用递归的消息集合,批量的消息可以通过压缩的形式传输并且在日志中也可以保持压缩格式,直到被消费者解压。

发布了43 篇原创文章 · 获赞 0 · 访问量 3901

猜你喜欢

转载自blog.csdn.net/zhangdx001/article/details/105089810