Kafka 为什么快?

前言

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

为什么快?

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

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

零拷贝

  • 传统的文件读取过程
    当我们将服务器的磁盘文件 读取 发送到 客户端,
    传统的过程大概是这样子:
    1. 操作系统将磁盘数据读取到 Kernel空间 缓存页 ReadBuffer 中。
    2. 应用程序将数据从 缓存页 ReadBuffer 中 拷贝到 应用空间
    3. 应用程序将数据从 Application Buffer 中 写入到 Socket Buffer 套接字中
    4. 操作系统将将数据从 Socket Buffer 再发送到 网卡,进入网络开始传输
传统Copy.png

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

  • Direct Memory Access
    什么是 DMA(Direct Memory Access) 呢?
    简单来说,
    一种可让某些硬件子系统去直接访问系统主内存,
    而不用依赖CPU的计算机系统的功能。
    也就是说,我们可以从将数据读取到 Kernel空间 缓存页 ReadBuffer,
    然后就可以直接发送到网卡 Buffer了。
    这样就可以大大的加快文件传输的速度了。
    也就是因为 DMA 技术,所以就产生了我们所谓的 Zero Copy 技术。
    而 kafka 使用的场景也正好可以完美的和这种技术切合。

追加写入

这个涉及到磁盘的设计原理...
感兴趣的可以自行百度搜索一下:磁盘读写原理。
这里我们就不多讨论了,
只需要知道磁盘的开销主要是两个方面:
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文件是怎么储存的?
  • Topic 和 Partition 的储存
    我们可以找到我们 Kafka 存储目录 (log.dirs定义的目录),
    可以发现该目录下有很多文件夹,
    这些文件夹的命名方式格式是 topic-partition,大概类似:

        helloTopic-0
        helloTopic-1
        helloTopic-2
    

    表示,该kafka 有一个 名为 helloTopic 的 Topci,其有三个分区:0,1,2

    这就是 Kafka 在 topic 和 partition 维度的储存方式了

  • Partition 里面的数据储存

    • Segment
      我们进入 一个 partition 的目录,可以发现一些类似下面这样的文件:
      (该文件是我造的,为了方便讲解)
      00000000000000000000.index
      00000000000000000000.log
      00000000000000000010.index
      00000000000000000010.log
      

    我们可以发现,该目录下有两种文件:.index.log
    同样也可以发现:indexlog 文件是成对的。
    那么其实kafka 的逻辑是这样的:
    一个 Partition 下会有多个 Segment,
    而一个 Segment 会包含 一个.index文件 和 一个.log文件
    从这些文件来看,
    我们这里就是两个 Segment:
    00000000000000000000 和 00000000000000000010

    看起来Segment的命名好像有点规律可循,
    实际上 Segment的命名 和 他保存的数据是有很大关系的。
    我们都知道,Kafka 消息的保存位置是通过一个 offset 来确定的,
    而这个 Segment 的命名就是其保存的消息的 offset 最小值+1。
    我们这里就是 Segment 00000000000000000000 保存了 offset 1 到 10 的消息
    而 Segment 00000000000000000010 保存了 offset 大于 11 的数据,
    并且 Segment 是可以排序的,所以当一个 请求来了,
    可以很快的通过二分查找定位到数据是在哪个 Segment。

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

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

  • Index 和 log 文件
    我们上面已经知道 一个Index 和 一个Log 文件就组成了一个 Segment。
    当来了一个消息请求,我们通过 offset快速定位到了 Segment,
    接下来,我们还得根据这个 offset 快速定位到具体消息的位置。
    而我们的 log 文件其实就是存储的具体的消息内容,
    而 index 文件则存储的是 log文件里面的消息的索引。

    说了这么多,我们最后一个列子来看,
    更进一步的了解下:

    1. 假如现在有一个 offset = 11 的消息请求过来了。
    2. 那么首先根据 offset 查找,可以定位到消息在 Segment 00000000000000000010 里面。
    3. 因为index保存的是 log文件的索引,
      所以我们在 Index 里面可以找到第offset - 10 = 1条数据,
      这条数据就会记录该 offset 消息在 log 文件的位置。
    4. 拿到 index 的索引,我们就可以快速找到该消息返回给客户端了

数据压缩

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

消息集

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

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容

  • 一、概述 Kafka作为一个支持大数据量写入写出的消息队列,由于是基于Scala和Java实现的,而Scala和J...
    服务端开发阅读 6,269评论 0 4
  • Kafka的基本介绍 Kafka最初由Linkedin公司开发,是一个分布式、分区、多副本、多订阅者,基于zook...
    join_a922阅读 1,410评论 0 1
  • Kafka的基本介绍 Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于z...
    小牛学堂阅读 296评论 0 0
  • Kafka是什么 Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于zoo...
    天堂鸟6阅读 198评论 0 3
  • 1. Kafka是什么 Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于...
    尼小摩阅读 286评论 0 1