kafka为什么快
Kafka为啥速度快
大家皆知kafka是分布式部署具有高可用性,brokers集群制+partition分区模式提升了容灾能力,数据是存储在磁盘上确保了数据的持久化。Redis速度快是因为其基于内存存储实现的数据库,内存读写省去了磁盘I/O的消耗,所以会很快,但是kafka是基于磁盘存储的,为啥具有高吞吐量呢
其一,顺序写入+mmfile
1、顺序写入
硬盘是机械结构,每次读写都会寻址->写入,其中的寻址操作是最耗时的,所以顺序读写就可以规避随机I/O的寻址操作,其顺序读写速度与内存基本可持平。
对于java的面向对象开发,内存开销是很大的,且随着堆内存数据的增多,java的gc时间会变长,使用磁盘操作的好处就出来了:
① 顺序写入磁盘顺序读写速度超过内存随机读写
② 顺序写入 JVM 的 GC 效率低,内存占用大。使用磁盘可以避免这一问题
③ 顺序写入系统冷启动后,磁盘缓存依然可用
基于顺序写入,想要删除数据怎么办呢?
不好意思,没得办法人工介入删除
但是,kafka数据是有保存时间的,时间到了,自动就删除了。另一个办法呢,就是可以基于partition分区大小进行数据控制
2、mmfile(Memory Mapped Files)
磁盘和内存在读写上有天然的差距,顺序读写也不一定能追的上内存,所以,kafka充分利用了现代操作系统分页存储来利用内存提高 I/O 效率
mmfile(内存映射文件),在 64 位操作系统中一般可以表示 20G 的数据文件,它的工作原理是直接利用操作系统的 Page 来实现文件到物理内存的直接映射,完成映射之后你对物理内存的操作会被同步到硬盘上
通过 mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存),也不必关心内存的大小有虚拟内存为我们兜底,使用这种方案省去了用户空间到内核空间复制的开销,极大提升I/O速度
问题:写到 mmap 中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用 flush 的时候才把数据真正的写到硬盘,存在一定的不可靠性
怎么解决这个问题呢:kafka提供了一个参数:producer.type 来控制是不是主动 flush。如果 Kafka 写入到 mmap 之后就立即 flush 然后再返回 Producer 叫 同步 (sync);写入 mmap 之后立即返回 Producer 不调用 flush 叫异步 (async)
其二:基于sendFile实现零拷贝
传统模式的拷贝方案:硬盘—> 内核 buf—> 用户 buf—>socket 相关缓冲区—> 协议引擎
零拷贝方案:硬盘—> 内核 buf—>socket 相关缓冲区—> 协议引擎
省去了内核缓冲区到 user 缓冲区,再由 user 缓冲区到 socket 相关缓冲区的文件 copy
其三:批量压缩
大多情况下,系统的瓶颈是网络I/O,而不是cpu或磁盘,kafka作为高吞吐量的流式处理系统,网络I/O速度尤为重要
1、如果每个消息都压缩,但是压缩率相对很低,所以 Kafka 使用了批量压缩,即将多个消息一起压缩而不是单个消息压缩
2、Kafka 允许使用递归的消息集合,批量的消息可以通过压缩的形式传输并且在日志中也可以保持压缩格式,直到被消费者解压缩
3、Kafka 支持多种压缩协议,包括 Gzip 和 Snappy 压缩协议
总结
Kafka 速度的秘诀在于,它把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络 IO 损耗,通过 mmap 提高 I/O 速度,写入数据的时候由于单个 Partion 是末尾添加所以速度最优;读取数据的时候配合 sendfile 直接暴力输出