Kafka 为什么快?

2019-09-19  本文已影响0人  code_solve

前言

本文只想从作者本身的认识来谈谈 kafka 为什么会这么快?
我们都知道 kafka 是基于磁盘的,
但是他的存储和读取速度确是非常的快的。
阅读本文前,你可能需要基本了解 kafka 使用 和 架构。

为什么快?

我们可以从以下几个角度来分析以下:

  1. 磁盘的读写速度
  2. 数据检索

零拷贝

传统Copy.png

一般而言,我们这样是没有问题的,
但是如果我们只是将数据完整的发送到网卡,
而不需要对数据做操作,
那么这样做无疑就显得很多余了。
于是我们就会想,
针对这种场景我们是不是可以直接将数据就从磁盘发送到网卡呢??

追加写入

这个涉及到磁盘的设计原理...
感兴趣的可以自行百度搜索一下:磁盘读写原理。
这里我们就不多讨论了,
只需要知道磁盘的开销主要是两个方面:
1.磁盘寻址 2.磁盘带宽,
而顺序读写就是大大减小了磁盘寻址的时间。
而 kafka 消息队列的设计,
则是完全基于顺序读写,
所以其速度还是相当可观的。

Memory Mapped Files

以下内容来自掘金
作者:java闸瓦
链接:https://juejin.im/post/5cd2db8951882530b11ee976
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

即便是顺序写入硬盘,硬盘的访问速度还是不可能追上内存。
所以Kafka的数据并不是实时的写入硬盘 ,
它充分利用了现代操作系统分页存储来利用内存提高I/O效率。
Memory Mapped Files(后面简称mmap)也被翻译成 内存映射文件 ,
在64位操作系统中一般可以表示20G的数据文件,
它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。
完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。
通过mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存),
也不必关心内存的大小有虚拟内存为我们兜底。
使用这种方式可以获取很大的I/O提升,
省去了用户空间到内核空间复制的开销,
但也有一个很明显的缺陷——不可靠,
写到mmap中的数据并没有被真正的写到硬盘,
操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘。
Kafka提供了一个参数——producer.type来控制是不是主动flush,
如果Kafka写入到mmap之后就立即flush然后再返回Producer叫 同步 (sync);
写入mmap之后立即返回Producer不调用flush叫异步 (async)。

上面这段话本人总结一下,
大概可以理解为以下两点:

  1. kafka写入数据的时候,
    是利用的系统的 mmap 机制,
    该机制最主要的特点可以理解成:
    mmap 会开辟一个 用户空间 和 内核空间 共用的空间
    这样通过网卡写过来的数据直接放到该空间,
    然后就可以直接写入到磁盘,
    而普通形式则是网卡写入的数据先到内核空间,
    然后拷贝到用户空间,
    想要写入数据,
    还得从用户空间拷贝到内核空间,
    再由内核空间写入到磁盘文件。
  1. 同时因为是内存,
    所以可能会导致数据丢失,
    如果想避免这种问题,
    客户端需要调用flush,
    对数据进行同步写入。

    不过这种概率比较低,
    因为存放的数据不是在用户空间,
    所以必须得整个机器宕机才会出现,
    并且我们一般有多副本,
    所以即使丢了,还可以恢复过来。

log index

上面说的都是关于磁盘这块速度的提升,
通过这些方法使得kafka 虽然是基于磁盘,
但是速度已经接近内存,
接下来我们再来看看kafka 数据的检索相关内容。

  1. kafka文件是怎么储存的?

这里额外提一下就是,因为分了 Segment,也方便了Kafka 对于过期数据的清理。

上面看完 Segment,我们来看看 Index 和 log 文件吧

数据压缩

Kafka的数据是支持压缩的,
这也是其快的一个重要方面

消息集

Producer会把消息封装成一个消息集发送给服务端,
而不是单条的消息;
服务端把消息集一次性的追加到日志文件中,
这样批量操作就减少了频繁的 IO操作。
其消息的保存格式是直接使用的二进制,
这也也省略了各种消息协议带来的开销。

本文就分享到这里,如果有错误欢迎指出。

如果觉的本文对你有帮助,欢迎点赞!!谢谢!!

上一篇 下一篇

猜你喜欢

热点阅读