为了账号安全,请及时绑定邮箱和手机立即绑定

Apache Kafka的重要设计:文件系统运用、零拷贝技术及批量处理

文件系统、零拷贝技术与批处理操作

这张图片由作者创作。

原文发表于https://vutr.substack.com ._

开始

如上一篇文章所承诺的,这周我们将继续了解Apache Kafka。我将介绍我对Kafka一些重要设计(如文件系统、零拷贝技术、批处理技术)的研究。

Kafka 使用文件系统功能

在继续之前,我们可以先了解一下操作系统(OS)页面缓存的概念。

这张图是作者自己画的。

现代的操作系统通常会借用未使用的内存(RAM)来作为页面缓存。经常访问的磁盘数据会被加载到缓存中,从而避免频繁直接读取磁盘。因此,系统运行速度更快,缩短了磁盘寻道延迟。如果某个程序需要内存,内核会回收用于页面缓存的内存。这样可以确保页面缓存不会影响系统的性能。

Kafka 使用操作系统的文件系统来存储数据,也因此利用了内核的页面缓存。操作系统并不会试图在内存中保留尽可能多的数据,而是在内存不足时将其刷新到磁盘之前,先将其全部加载到页面缓存中,再将其刷新到磁盘。

因此,这种方法有助于Kafka简化代码库,因为操作系统负责处理页面缓存逻辑。此外,这种方法也对Kafka有利,因为Java虚拟机存在一些痛点。

  • 存储对象所导致的高内存消耗。
  • 当堆内对象数量增加时,垃圾收集器的运行速度会变慢。

通过利用操作系统文件系统而不是将消息缓存在内存中的Java对象,Kafka可以解决上述两个问题。

要顺序访问的模式

得知 Kafka 使用文件系统进行数据存储和缓存后,你可能会想,“由于磁盘操作总是比内存慢,这会不会影响 Kafka 的性能表现?”

这里的关键在于访问模式。毫无疑问的是, 在随机访问的情况下,磁盘速度会比RAM慢,而在顺序访问的情况下,磁盘则可能略胜一筹。我们来仔细看看这些模式:

  • 随机存取是一种检索或存储数据的方法,其中数据可以按任何顺序随机访问。
  • 循序存取是一种检索或存储数据的方法,其中数据按顺序存取。

Kafka 是这样设计的,使写入(生产者写数据)和读取(消费者读数据)按顺序进行。让我们来看看它们是怎么做到这一点的。

来写

作者的这张图。

在 Kafka 中,消息是通过主题进行分组的。每个主题会被拆分成多个分区。每个主题的分区对应一个逻辑日志流。物理上,一个日志是由一组大小相近的段文件组成(例如,每个段文件大约为 1GB)。每当生产者向分区发布消息时,代理会将消息追加到最后一个段文件。任何时候只有一个段文件处于活动状态并接受数据写入;一旦段文件达到大小限制就会被关闭,并且 Kafka 会为后续写入打开一个新的段文件。

Appending at the end of段文件末尾的追加操作,确保了Kafka中的数据写入是顺序的。

《读》

这张图是作者自己绘制的。

消费者总是按顺序从特定分区中消费消息。Kafka中存储的消息没有消息ID,每条消息有一个逻辑偏移量。这避免了维护额外索引结构的开销,这些索引结构将消息ID映射到消息的实际位置。Kafka消息的偏移量递增但不一定是连续的;因此,要找到下一个消息的偏移量,需要进行这样的计算:为了获取下一条消息的偏移量,需要把当前偏移量加上当前消息的长度,就像数组数据结构处理随机访问那样。

除了包含实际数据的日志文件外,代理服务器还拥有另外两个索引文件,这些文件有助于更快地定位所需的分段文件。第一个索引将偏移量对应到分段文件及其内部位置,使代理能够快速找到给定偏移量的消息。后者将时间戳对应到消息偏移量;此索引在通过时间戳查找消息时使用。Kafka使用内存映射文件技术来读取这些索引文件,这使得Kafka可以将索引文件读取得就像它们直接位于内存中一样。

该索引将偏移量映射到消息在段日志中的位置。Travis Jeffery(2016 年)撰写的《Kafka 存储内部工作原理》。原文链接

在开始拉取消息时,消费者首先向代理请求开始消费的起始偏移量。然后,代理通过索引文件定位包含请求消息的分段文件,并将数据发送给消费者。消费者接收到消息时,计算下一个消息的偏移量,并在下一次请求中使用它。

零复制

使用文件系统也有助于Kafka在幕后实现零拷贝优化。需要注意的是,零拷贝操作并不意味着完全没有数据复制。它只是确保不会进行不必要的复制。这项优化并非专为Kafka首次发明,它只是利用了操作系统现有的这项技术。

我们先来看看原始数据传输的流程,然后再来看看零拷贝技术是怎样的工作方式。

数据传输流程

作者自制的图片。

在从磁盘读取文件并通过网络传输的典型流程中,数据会被复制四次,同时用户模式和内核模式之间会发生四次上下文切换。流程如下所示:

  1. 它从磁盘读取文件内容并存储在操作系统页面缓存(读缓冲区)中。此步骤需要从用户模式切换到内核模式。
  2. 数据从读缓冲区复制到应用程序缓冲区,同样这也需要模式切换,从用户模式转到内核模式。
  3. 数据接着被复制到套接字缓冲区。同样,这需要从用户模式切换到内核模式。
  4. 在将数据发送到套接字缓冲区之后,返回用户模式进行上下文切换。然后将数据从套接字缓冲区复制到网络接口控制器 (NIC)中。
  5. NIC将数据发送到目标位置。

为了更清楚地说明:

用户模式和内核模式的模式切换:在现代操作系统中,软件运行在用户模式和内核模式。用户模式限制了对系统资源的访问,而内核模式则允许完全访问。当用户应用程序需要内核级别的访问权限,比如访问硬件设备时,它会通过系统调用请求操作系统从用户模式切换到内核模式。这种切换称为模式切换,包括保存当前处理器状态、改变模式和加载新的状态。

网络接口控制器(NIC)管理计算机与网络之间的接口,将数据转换成用于网络传输的信号,并接收传入数据供计算机处理。

套接字缓冲区是一种内存空间,用于内核临时存储网络套接字的传入和传出数据包,管理应用程序与网络之间的数据流动。

零拷贝流

作者绘制的图片。

借助零拷贝优化,数据可以直接从页面缓存复制到套接字缓冲区。在Unix系统下,这种方法通过一个sendfile()系统调用来实现。它可以直接从一个file descriptor复制数据到另一个,而不需要在使用read()write()系统调用时在用户空间进行数据传输。因此,这种优化可以帮助Kafka绕过原始数据传输过程中的第二和第三步。当Kafka利用零拷贝技术时,流程可以概括如下:

  1. 数据从磁盘复制到页缓存。
  2. 然后,数据通过 sendfile() 调用直接从页缓存复制到网络接口。
  3. 网卡将数据发送到目标。

因此,上下文切换次数从四次减少到两次,并且数据复制不再需要复制到Kafka应用中。此外,在第一步中,数据只会被一次性复制到页面缓存里,在需要时复用,而不是每次读取时不再在内存中移动并在用户空间中复制。

重要的是,从生产者发送到磁盘,直到代理将数据转发给消费者,Kafka的数据格式在这一过程中始终保持一致。使用相同的格式让Kafka能高效利用零拷贝技术,并避免解压和再压缩消息。

批量处理

由于后台文件系统使用,客户端向代理发送过多的小请求可能会影响Kafka的性能。为解决这一问题,Kafka协议提供了一种消息集抽象,有助于将消息进行分组。这有助于减少网络往返中发送大量单条消息请求的开销。

除了网络性能的好处之外,批处理还帮助代理更高效地写入消息到磁盘;代理不是逐条追加消息,而是批量追加消息到磁盘。这使得Kafka能够进行更大的连续磁盘读写操作。

此外,更重要的是,如果网络带宽成为瓶颈时,Kafka支持通过高效的批量格式压缩消息批次。消息批次可以被分组、压缩并发送给broker。

结尾

我们在本文中刚刚讨论了一些 Kafka 的设计决策。首先,Kafka 通过操作系统文件系统进行读写操作。其次,由于使用文件系统并保持物理数据格式的一致性,Kafka 可以利用零拷贝技术,使数据传输更加高效。最后,我们看到批量处理消息如何帮助 Kafka 提升性能。下周我们将继续深入了解 Kafka 的生产者部分。

那麽,下周再見 :)

参考文献

[1] Kafka 官方页面

[2] 格温·夏皮拉,托德·帕利诺,拉吉尼·希瓦拉,克里特·佩蒂,Kafka 权威指南:实时数据与大规模流处理 (2021)

_[3] 维基百科-内存映射文件(https://en.wikipedia.org/wiki/Memory-mapped_file)_

_维基百科 — 页面缓存 页面缓存_

[5]Linux 吃掉了我的内存

安德烈·扎博洛茨基的《Kafka是如何在写入磁盘时保持高性能的?》(2021。)

_【7】Stanislav Kozlovski,_零拷贝入门(https://2minutestreaming.beehiiv.com/p/apache-kafka-zero-copy-operating-system-optimization) 2023

[8] Travis Jeffery, [Kafka 的存储内部工作机制](https://medium.com/the-hoard/how-kafkas-storage-internals-work-3a29b02e026) ((2016 年))

我的通讯稿是一封每周的博客风格电子邮件,在这封邮件中,我记录从比我更聪明的人那里学到的东西。

所以,如果你想和我一起学习和成长,请在这里订阅吧:https://vutr.substack.com

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消