『攻城狮Bilbo』Kafka为什么会这么快
在系统设计中 , 会用到消息中间件来做服务异步化 , 系统解耦 , 或者是做流量削峰 , 常用的消息中间件有rabbitMq , activeMq以及阿里的RocketMq等等 , 都各自有各自的优势 , 但是就吞吐量来说 , kafka是其中的佼佼者 。 在单机情况下 , 网友做的对比如下:
文章图片
性能对比
为什么kafka会这么快呢?发布订阅模式
一个普通的发布订阅模型如下图所示:
文章图片
发布订阅模式
以kafka为例 , 生产者产生消息 , 并将消息Push到kafka集群 , 消费者主动去kafka集群Pull数据 。 这种模型有个好处 , 消费的速率完全由消费者控制 , kafka集群类似于一个蓄水池 , 避免因生产者产生消息过快消费者来不及消费而导致消费者被压垮的现象 。
kafka为什么快要从两方面分析 , 生产者产生的消息写入集群时快和消费者消费消息时从集群读取快 。 写入快
写入快主要是两方面原因:顺序写入和MMFile 。
顺序写入
kafka将消息存储在硬盘 , 通常认为硬盘的读写是比较慢 , 但是为什么kafka快呢?平时所说的磁盘读写慢是指随机读写比较慢 , 因为磁盘每次随机读写都要物理寻址 , 这是非常耗时的操作 , 顺序读写的速度还是比较快的 。 如下图所示:
文章图片
顺序写入
kafka每次收到新的消息之后都会将消息存储在尾部 , 按照顺序存储消息 。 但是消息一旦存储无法删除 。
当消费者消费时也是顺序消费 , 每个消费者会有一个偏移量 , 记录当前消费的消息的位置 。 如下图所示:
文章图片
顺序消费
MMFile
MMFile是指MemoryMappedFiles , 即内存映射技术 。 操作系统为了解决内存和硬盘读写速度之间的差异 , 采用了内存映射技术 , 内存被划分为若干页 , 每一页被映射到一块磁盘空间 , 因为内存是远远小于磁盘空间的 , 所以分页经常会按照一定的算法加载到内存 , 例如先进先出(FIFO) , 最近最少使用(LRU)等 。 内存中分页和磁盘空间对应 , 操作系统会在合适的时候将内存分页中的数据定时刷磁盘中去 。 这种方式为什么可以提高写入效率呢?通常CPU执行过程中为了安全分为内核态和用户态 。 只有内核态才能操作iO设备 , 内存空间分为内核空间和用户空间 。 通常内存中的数据写入到磁盘要以下几步:
文章图片
write操作
数据会先从用户空间拷贝到内核空间 , 然后再由内核空间写入IO设备 。 而MMFile则省去了一次用数据从户空间到内核空间复制的开销 。 读取快
读取快主要是因为零拷贝(ZeroCopy)技术 。 上面介绍到数据从内存空间写入磁盘的步骤 , 那么从磁盘读取数据刚好相反 , 具体过程如下:
文章图片
【『攻城狮Bilbo』Kafka为什么会这么快】read操作
数据先从磁盘读取到内核空间 , 然后再从内核空间复制到用户空间 , 然后再到Socket , 最后传输到消费者 。
Linux提供了一种sendFile系统调用 , 可以将数据直接由磁盘拷贝到内核空间 。 省去了一次数据从用户空间到内核空间的复制 。 这就是所谓的零拷贝技术 。
上面从读写两个角度分析了为什么kafka吞吐量高 , 其实还有一个重要的原因 。 批量数据压缩