前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kafka 为什么快?

Kafka 为什么快?

作者头像
solve
发布2019-10-30 20:02:15
6660
发布2019-10-30 20:02:15
举报
文章被收录于专栏:大数据技术栈大数据技术栈

前言

本文只想从作者本身的认识来谈谈 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 使用的场景也正好可以完美的和这种技术切合。

追加写入

这个涉及到磁盘的设计原理... 感兴趣的可以自行百度搜索一下:磁盘读写原理。 这里我们就不多讨论了。 但是根据 LinkedIn 的一个实验数据可以大致了解到, 磁盘的 随机读写 和 顺序读写 是有比较大的差距的, 而 kafka 消息队列的设计, 则是完全基于顺序读写, 所以其速度还是相当可观的。

Memory Mapped Files

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

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

上面这段话本人是看的有点似懂非懂, 但是大概可以理解为以下两点:

  1. kafka写入数据的时候,并不是直接写磁盘。 而是写入一个内存空间 — mmap, 然后通过mmap的缓存加快速度。
  2. 同是因为是内存,如果服务挂掉,会导致数据丢失, 如果想避免这种问题, 客户端需要调用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操作。 其消息的保存格式是直接使用的二进制, 这也也省略了各种消息协议带来的开销。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.09.19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 为什么快?
    • 零拷贝
      • 追加写入
        • Memory Mapped Files
          • log index
            • 数据压缩
              • 消息集
              相关产品与服务
              对象存储
              对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档