新老男人快报新看点
首页 >> 科技咖 >> 正文

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega

日期:2021-04-11 10:39:55 来源:互联网 编辑:小狐 阅读人数:476

审校 | 蔡芳芳

1引言

流式应用程序通常从各种各样的 例如,传感器、用户、 并发地采集数据,并形成一个事件流 stream of s使用单个流来捕获由多个数据源生成的并行数据流可以使得应用程序能够更好地理解数据,甚至更有效地处理数据。例如,将来自一组传感器的数据输入到单一数据流中,就可以使得应用程序通过引用单一数据流来分析所有这类传感器数据。当这些单个的流可以以高并行度读取时,应用程序就能自行决定如何映射自身的抽象设计到这些流进行数据读取,而不是被人为的基础设施限制而决定。

并行化在处理流数据时也很重要。当应用程序分析流中的数据时,它们通常依赖并行处理来降低延迟和提高吞吐量。为了在读取流式数据时支持并行性,流存储允许在数据写入时,根据事件负载进行分区。这通常基于路由键 (routing keys) 的支持。通过分区,应用程序可以保留以应用本身概念(如标识符)的顺序。在每个分区内,数据是有序的。在 Pravega 中,Stream 的并行单位被叫做 segment,而在基于 topic 的中 (如 Apache Kafka 和 Apache Pulsar)它被称为 partitions。Pravega 的 stream 可以自动根据负载的变化改变 segment 的数量。

在最多有 100 个写入端和 5000 个 segment,数据流量在 250MBps 时,Pravega 可以在所有情况下都维持 250MBps 的速率。而 Kafka 在 5000 个 partition 时只有不到 100MBps。Pulsar 则在大多数情况下会直接崩溃。

Pravega 可以保证在 95% 中位数时,延迟在 10 毫秒以下,而 Kafka 的延迟却高达几十毫秒。对于 Pulsar,它有高达几秒的延迟,并且是在我们仅仅能成功的那次。

为了公平起见,我们已经了 Pulsar 的其他配置,以了解在哪些条件下它表现出良好的性能结果。因此,我们另外展示了一个对 Pulsar 更有利的配置,并且不会导致它经常崩溃。但这个配置对于我们的来说没有那么大的,如我们在下面进一步解释的那样。

在下面的章节中,我们将解释是什么能够让 Pravega 在这种情况下表现得更好,并详细介绍我们的环境设置、实验过程和结果。

2为什么 Pravega 性能更好?

我们介绍一些关于 Pravega 添加路径 (append path) 的设计特点,这些特点对于理解结果很重要。我们还讨论了一些有关设计的权衡,并阐述了我们为什么在 Pravega 上选择这种。

Pravega 的添加路径 (append path)

Pravega 的添加路径 (append path) 包括三个相关部分:

添加数据的客户端

Segment Store,用以接收数据添加的请求,记录其日志并持久化存储

持久化的日志存储,由 Apache BookKeeper 实现

下图阐释了 Pravega 的添加路径 (append path)

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega(图1)

Pravega 的添加路径 (append path)

客户端添加由程序源生成的数据,并尽可能对这些数据进行批处理。在服务端收集客户端的批处理数据,这样做的好处时可以避免缓冲数据,但要注意是由客户端来控制批处理何时开始和结束。客户端使用了一种批处理跟踪的启发式算法,这个算法通过输入速率和响应反馈来估计批处理的大小。有了这样的估计,客户端就可以决定何时关闭批处理 (代码在 AppendBatchSizeTrackerImpl.java)

segment store 在一个称为 segment 容器 (segment container) 的组件中执行这第二级批处理。一个 segment store 可以同时运行多个 segment 容器,并且每个容器都有自己的持久化日志 (durable log) 并追加到其中。这些 segment container 在单个 segment store 实例中可以并行地进行数据的 append 写入。

每个 segment 容器负责在 Pravega 集群中所有 stream 中一部分 segment 上的操作。在全局上,集群会协调哪些 segment 容器对应哪些 segment store 实例。当增加 segment store 实例时 (例如扩大规模) 或减少 segment store 实例时 (如缩减规模或局部宕机)segment 容器集合将跨现有 segment store 实例重新平衡。

持久性日志目前是通过 Apache BookKeeper ledgers 实现的。Bookie(BookKeeper 的存储) 将数据添加请求的日志记录到 ledgers 中,并在将数据添加加到 journals 之前执行另一层合并。这第三层的合并又是一量处理来自不同 segment 容器数据的机会。在我们用于 Pravega 的配置中,为了保证持久性,bookie 只对将数据写入 journal 的分 segment 容器做出响应。BookKeeper 还维护其他数据结构,但它们与本文的讨论无关。

低延迟、高吞吐量和持久性

低延迟对于许多流式应用程序是至关重要的。这些应用要求数据在生成后不久就可以进行处理。高吞吐量同样适用于需要从许多获取大量数据的应用程序。如果不能够维持高吞吐量的输入,应用程序在数据峰值时可能会面临不得不需要局部减载的危险。最后,在分析并处理这些流时,数据的丢失可能导致不正确的结果,因此,持久性对于企业应用程序也是至关重要。

在我们评估的所有三个中,Pravega 在这三个方面总体上了最好的结果。与 Kafka 和 Pulsar 相比,它在保持高吞吐量和低延迟的同时保证了持久性。Kafka 则在这三个方面做出了不同的选择。与其他两种配置相比,默认情况下它可以获得更高的吞吐量和更低的延迟,因为它不会等待磁盘的写入成功,但这种选择牺牲了持久性。Pulsar 能够像 Pravega 一样保证持久性,因为它建立在 BookKeeper 的基础上 ; 尽管如此,它似乎并没有实现一个写路径 (write path)能够保证在多写入客户端和多 partition 的情况下依然足够高效,正如之后与其他两个相实验结果所展示的那样。

3评测与配置一览

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega(图2)

在我们性能中使用的主要设置

在我们之前的博客中,我们对 Pravega、 Apache Pulsar 和 Apache Kafka 使用了相同的副本方案: 3 个副本,每次收到 2 个确认进行写入。对于数据持久性,Pravega 和 Pulsar 在默认情况下保证每次写入的数据持久性,并且我们保留这种行为。对于 Kafka,我们了两种配置: 1) 默认配置 no flush,这种配置下数据不会显式地刷到磁盘中,那么在有些相关的故障发生时可能导致数据丢失 ; 2) 磁盘刷新配置,其通过每次写入刷入磁盘的方式保证数据的持久性。日志在所有的都写入了一个 NVMe 硬盘,这样我们可以理解这三个如何在并发度上升的时候使用它。

我们使用 OpenMessaging 基准来运行我们的实验 (请参阅这里的部署说明并在 Pravega 实验中使用此版本)我们将输入数据速率固定在 250MBps(每个事件 1KB)而不是探索和评估的最大吞吐量。我们的目标是在客户端数量和 segment/partition 的数量改变时,比较的不同的行为。这样的设置使得实验可以保证数据注入的固定以减小其他因素对性能的影响。为了完整起见,我们仍然在博客的末尾讨论了这些的最大吞吐量。

中的生产者和消费者线程分布在很多虚拟机上 (详情请参见上表中的 Producers/Consumers 行)每个生产线程和消费线程都使用一个专用的 Kafka、 Pulsar 或 Pravega 客户端实例。基准的生产者线程使用 Kafka 和 Pulsar 中的 producer 或 Pravega 中的 writer ,而基准的消费者线程使用 Kafka 和 Pulsar 中的 consumer 或 Pravega 中的 reader。

在 Pravega 的具体案例中,写入端使用了连接池技术: 这个特性允许应用程序使用一个公共的网络连接池 (默认情况下每个 segment store10 个连接) 来处理大量的 segment 连接。

数据输入和并行性

我们要评估的第一个方面是增加 segment 和客户端数量对吞吐量的影响。下面的图表显示了 Pravega、 Kafka 和 Pulsar 的吞吐量,包括不同数量的 segment 和生产者。每一条线对应于在同一个工作负载下,向单一一个 stream/topic 追加不同数量的生产者。对于 Kafka 和 Pulsar,我们也绘制了其他配置下的图线。这些配置以牺牲功能性(持久性或者是 no key)为代价,为这两个了更好的结果。

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega(图3)

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega(图4)

该实验可以通过 P3 程序复现,它使用以下的工作负载和配置文件作为输入。他们分别是 Pravega(工作负载,配置)Kafka(工作负载,配置)和 Pulsar(工作负载,配置)这些的原始基准输出可在此处获得:Pravega,Kafka(不 flush)Kafka(flush)Pulsar,Pulsar(有利配置)

通过研究上面的实验图表,我们观察到以下关于吞吐量和并行性的关系:

Pravega 是这些中唯一可以在 250MBps 数据流,5000 个 segment 和 100 个生产者的负载下稳定工作的。这表明 Pravega 添加路径 (append path) 的设计可以有效地处理高并行下的工作负载,特别是当许多写入端的小数据的追加写在 segment 容器中进行批量化处理的设计。

值得一提的是,当我们在 Kafka 的配置中开启了 flush 强制刷新到磁盘以确保数据持久性,吞吐量有着显著的下降 (例如对于 100 个生产者和 500 个分区时,有 80% 的下降)虽然强制刷新到磁盘会对造成一定的性能损失,但是这个实验表明了在超过十个分区且保证持久性的情况下,吞吐量会有非常明显的损失。

Pulsar 在我们试验过的大多数配置情况下都会崩溃。为了了解 Pulsar 稳定性问题的根本原因,我们换了一个更有利的配置:

不使用路由键来写入数据 (这样会牺牲数据的有序性并且降低实际的写入并行性)如果启动的话,我们会在 Pulsar 的 broker 中发现关于 Bookkeeper 的 DBLedgerStorage 不能够跟上写入的速度的错误。

通过这种配置,Pulsar 可以得到比基本情景 (如 10 个生产者) 更好的结果。然而,当实验中有大量的生产者和分区时,它仍然显示出性能下降和最终的不稳定性。注意,在写操作中不使用路由键是 Pulsar 性能提升的主要原因。在内部,Pulsar 客户端通过创建更大的批处理并以 round-robin 的方式使用 segment 来优化没有键的情况 (参见文档)

在写入流数据时,延迟也和吞吐量一样重要。接下来,我们展示了 95% 中位数时写入延迟和 segment/ 生产者数的关系。请注意,在本节中,我们展现了所有的延迟数据,而不考虑它们是否达到了要求的高吞吐量。

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega(图5)

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega(图6)

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega(图7)

通过研究上面的实验图表,我们重点总结出了以下结论:

Pravega 在 95% 中位数的情况下<10 毫秒的延迟,而 Kafka,即使修改配置使其不刷新到磁盘,也有更高的延迟。回想一下上一节,Pravega 在有很多 segment 和生产者的时候也能达到目标的高吞吐量,而 Kafka 没有。

Kafka 在保证数据持久性 (即打开 flush 开关) 的模式下,延迟比默认配置更高了 (95% 中位数的延迟在 100 个生产者和 500 个 segment 的情况下达到了 13.6 倍的延迟)在高并行的需求下,应用程序可能不得不在数据持久性和高并行的性能下二选一。

基本配置下的 Pulsar 只能在 10 个 partition + 10 个生产者的情况下保持低延迟。任何提升 partition 数量或者写客户端数量都会导致不稳定。

当使用更有利的配置时,Pulsar 在 10 个生产者的情况下可以获得<10 毫秒的延迟。对于 100 个生产者,延迟会随着 partition 数量的增加而迅速上升。

与 Kafka 相比,Pravega 拥有更低的延迟,甚至对于默认的不等待磁盘返回写入确认的 Kafka 配置来说也是如此。对于 Pulsar,的不稳定性不允许我们对建立的配置进行干净的比较。对于更有利的 no key + 等待所有 bookie 返回的配置下,Pulsar 能在 10 个生产者下保持了<10 毫秒延迟,但是对于 100 个生产者的话延迟会增加的很快。

关于最大吞吐量的附注

虽然我们在上面的实验中使用了一个固定的目标速率,但是我们还想了解这些在我们的场景中能够达到的最大吞吐量。为了缩小分析范围,我们固定使用 10 个生产者,对比了在 10 和 500 个 segment/partition 时的情况。

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega(图8)

这些的原始结果可以在这里看到。

从基准的角度来看,Pravega 可以在 10 和 500 个 segment 下达到 720MBps 的最大吞吐量,换算在磁盘级别则大约是 780MBps。这个差异是由于 Pravega 和 BookKeeper 添加了额外的元数据开销 (例如 Pravega 的 segment 属性)这个成绩非常接近同步写入磁盘的最大速度(约 803MBps)实验如下:

对于自定义配置的 Pulsar,我们可以在基准上可靠地获得近 400MBps 的吞吐量。我们还了将客户端的批处理时间增加到 10 毫秒,这使得吞吐量略有提高 (515MBps)尽管如此,我们注意到这远远不是磁盘写入的最大速率,我们怀疑这是由于使用了路由键,因为它减少了 Pulsar 客户端批处理的机会。更糟糕的是,随着分区数量的增加,Pulsar 的吞吐量很快受到了限制。这个结果表明,主要依赖客户端来聚合数据成批具有很大的局限性。

对于有 10 个 partition 的情况,我们观察到,当 Kafka 保证持久性 (“flush” 模式) 时,它可以在等待写返回时达到 700MBps 和不等待写返回时达到 900MBps。请注意,这只发生在有 10 个 partition 的情况下,因为当有 500 个 partition 时,吞吐量分别降至 22MBps 和 140MBps。

在写入流数据时,Kafka,vs,Pulsar,vs,Pravega(图9)

在不同 segment 或写入者的情况下,iostat 监测的平均磁盘写入的大小的累积分布函数

4总结

随着越来越多的需要读写并行化的实际使用情况,流存储有效地、高效地适配这些工作负载变得至关重要。许多这样的应用程序是云原生的,并且它们需要有效地伸缩和并行化这些工作负载的能力。

谷歌“宠爱”升级,Rust 大步跨入 Android 平台

Mesos已死,容器永生

90亿美元Java纠纷案反转:安卓中复制的代码属于合理使用

Java 微服务能像 Go 一样快吗?

北京Q1平均月薪达11187元;拼多多回应被告诈欺;京东、美团等承诺不用大数据杀熟 Q资讯

开启你的创作之路吧~

本文相关词条概念解析:

数据

数据就是数值,也就是我们通过观察、实验或计算得出的结果。数据有很多种,最简单的就是数字。数据也可以是文字、图像、声音等。数据可以用于科学研究、设计、查证等。数据背景是接收者针对特定数据的信息准备,即当接收者了解物理符号序列的规律,并知道每个符号和符号组合的指向性目标或含义时,便可以获得一组数据所载荷的信息。数据作为信息的载体,当然要分析数据中包含的主要信息,及分析数据的主要特征。数据(Data)是载荷或记录信息的按一定规则排列组合的物理符号。

延伸 · 推荐

基于,Flink-ClickHouse,+,ClickHouse,所谓点击流

DIM 层:维度层,MySQL 镜像库,存储所有维度数据。ODS 层:贴源层,原始数据由 Flume 直接进入 Kafka 的对应 topic。DWD 层:明细层,通过 Flink 将 Kafka 中...

网友评论