kafka读写速度快的原因

kafka的消息是保存或者缓存在磁盘上的,一般认为在磁盘上读写数据会降低性能,因为寻址比较消耗时间。但是实际上,kafka具有高吞吐性,轻松支持
每秒百万级的写入请求,在海量日志处理场景下广泛应用。
kafak读写速度快的原因:
一:生产者写入数据
kafka会把收到的消息都写入到硬盘中,它绝对不会丢失数据,为了优化写入速度kafka采用了两个技术:顺序写入和内存映射文件
1.顺序写入
磁盘读写有两种方式,一种是顺序读写,一种是随机读写,在磁盘的顺序读写情况下,其速度与内存读写速度持平。
因为磁盘是机械结构,每次读写都会先寻址,再写入,其中寻址是一个机械动作,最耗费时间,所以当顺序读写时,不需要寻址,也就提高了速度。
甚至其速度快于内存的随机读写。而且linux对于磁盘的读写优化也比较多,包括read-ahead和write-behind,磁盘缓存等。如果在内存做这些操作,
java对象的内存开销很大,另一个是随着堆内存数据的增多,java的GC时间会变的很长,使用磁盘的好处有:
1.磁盘的顺序读写超过内存的随机读写
2.java的GC效率低,内存占用大,使用磁盘可以避免这个问题
3.系统冷启动后,磁盘缓存依旧可以用
kafka中的有不同的topic,一个topic又可以有一个或者多个partition,每一个partition都是一个文件,topic收到消息后,会将这些数据插入
partition文件的末尾。但是这种方法不可以删除数据,所以kafka会把所有的数据都保留下来,再根据时间或者partition文件的大小进行删除。
每一个消费者
2.内存映射文件:
内存映射文件相当于一块虚拟内存,大小有20G,可以保留一个地址空间的区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自
一个已经存在于磁盘上的文件,当使用了内存映射文件时,当你在处理它在磁盘上对应的那个文件时,就不必再对文件执行IO操作,这样极大提高
了IO效率,因为这相当于读写内存一样读写磁盘。但是这有一缺点是不可靠,因为在内存映射文件中的数据没有真正的写到硬盘。只有当系统调用
flush的时候才会把数据真正的写入磁盘。kafka有一个参数producer.type是用来控制是不是主动flush。
二:消费者读取数据:
1.基于sendfile实现zero copy
传统模式下,当对一个文件进行传输时,具体的流程如下:
1.调用read函数,文件数据被copy到内核缓冲区
2.read函数返回,文件数据从内核缓冲区copy到用户缓冲区
3.write函数调用,将文件数据从用户缓冲区copy到内核与socket相关的缓冲区
4.数据从socket缓冲区copy到相关协议引擎
传统模式下进行网络文件传输的过程中,实际上进行了四次copy操作。但是sendfile系统调用减少了多次copy,提升文件传输效率。
kafka把所有的消息都存储在一个个的文件中,当消费者需要数据的时候,kafka将文件直接通过sendfile的方式发送给消费者,提高了效率。
并且该方式还提供了从指定偏移量发送文件的功能,消费者保存着偏移量,每次请求时,都会发送这个偏移量,sendfile会把这个文件按照
指定偏移量进行发送。
2.批量压缩:
很多时候,系统的瓶颈不是CPU和磁盘,而是网络IO,kafka会对数据进行批量压缩,虽然这样会消耗CPU资源,但是对kafka而言,这些CPU资源
很少,况且相对于CPU资源,由于批量压缩而减少的网络IO更值得kafka考虑。
总结:kafka速度快的原因就在于,把所有的消息都变成一个个文件,并通过合理的批量压缩形式减少网络IO损耗,通过内存映射文件提供IO速度,写入数据的
时候由于是末尾添加,所以速度最优,消费时,通过sendfile方式达到减少copy操作,直接输出,提升文件传输效率。

kafka的文件存储机制:
kafka中可以有多个不同的topic,用来存储不同类型的数据。而每一个topic下又有多个或者一个partition,每一个partition在实际中是一个目录。
在kafka的配置文件中可以配置partition文件存放的目录。每一个partition相当于一个巨型文件被平均分配到多个大小相等的segment数据文件中,
每个segment文件大小不一定相等,主要为了方便删除过期的数据,而每个partition只需要支持顺序读写就完事了。
segment文件由两部分组成,一个是数据文件,以.log结尾,一个是数据文件对应的索引文件,以.index结尾。segment文件命令规则是,第一个segment
文件是16位的0,后续的segment文件是以上一个segment文件最后一条消息的偏移量为名作为名字的。这样做主要是为了方便消费者通过索引文件快速的
找到自己需要的消息。

kafka高效文件存储设计的特点:
1.kafka把topic中的一个个partition分成多个小文件段,通过多个小文件段,容易定期清除数据,减少磁盘的占用
2.通过索引信息可以快速的找到需要的信息
3.通过索引元数据全部映射到内存,可以避免segment file的IO磁盘操作
4.通过索引文件稀疏存储,可以大幅度降低索引文件元数据占用的空间。

kafka中的topic有多个partition,是如何保证顺序读取的?
kafka的partition内存时强有序的,但是partition之间不是有序的。

一个分区只能被同组的一个消费者消费,同组的消费者起到均衡作用。

当消费者数量大于主题的分区数量:
如果某个主题只有一个分区,而现在启动两个消费者去消费该主题。并且这个两个消费者同属于一个消费者组,那么只有一个消费者能够消费得到数据,另一个消费者
空闲。即同一个分区内的消息只能被同一个组中的一个消费者消费,当消费者数量多于分区数量时,多于的消费者空闲。分区的数量决定了该主题在同一组中可被均衡
的程度,比如有4个分区,则可在同一组中被最多4个消费者均衡消费。

当消费者数量小于或等于分区数量:
比如一个主题有三个分区,在同一个消费者中启动2个消费者去消费该主题,则其中一个消费者会消费两个分区,另一个消费者消费一个分区。如果数据在分区之间是
均匀分布的话,消费两个分区的消费者所消费的数据量是另一个的两倍。但是如果在这个消费者组中再启动一个消费者的话,也就是有三个分区和三个消费者,那么
分区与消费者的将会一一对应。

多个消费者组:
当多个消费者组消费同一个主题时,比如某主题有三个分区,同时被两个消费者组A和B消费,A中有三个消费者,B中一个消费者。
那么A中的三个消费者会一一对应于主题的三个分区,而B中的一个消费者会独立消费该主题的三个分区。

对于同一个主题,不同的消费者组之间互不影响。

你可能感兴趣的:(大数据集群,kafka,读写速度,内存,磁盘)