如何避免在火花流中排队批次

时间:2021-03-16 15:12:09

标签: apache-spark apache-kafka spark-streaming spark-kafka-integration

我使用 Direct Streaming 进行 Spark 流式传输,并且正在使用以下配置

<块引用>

批次间隔 60s

spark.streaming.kafka.maxRatePerPartition 42

auto.offset.reset 最早

当我使用最早的选项开始流式批处理时,为了更快地从 Kafka 消耗消息并减少延迟,我将 spark.streaming.kafka.maxRatePerPartition 保持为 42。所以它应该消耗 42 x 60s x 60 分区 = 151200每批记录。

我有两个问题

  1. 我看到最初的几个批次正确消耗了 151200 条记录,在后面的批次中逐渐减少,即使有很多来自 kafka 的记录要消耗。请看下面的截图。可能是什么原因
  2. 我看到很多批次都在排队。我们怎样才能避免这种情况。

是否可以实现以下场景 我们将批处理间隔设置为 60 秒,如果每个批处理在 60 秒内运行,则下一个批处理可以准时开始。如果一个批次的时间超过 60 秒,我们不希望下一个批次进入队列。现有运行完成后,下一次运行可以通过选择该时间之前的记录开始。这样我们就不会出现延迟,也不会排队批次。

Spark UI - Screenshot for question 1

1 个答案:

答案 0 :(得分:0)

您观察到的是 Spark 背压机制的预期行为。

您已将配置 CrossAxisAlignment.center 设置为 42,并且根据您的计算,作业将开始获取

spark.streaming.kafka.maxRatePerPartition

查看附加屏幕截图中的时间(处理时间),作业以该数量的记录开始。

但是,由于处理所有这 151200 条记录需要超过 60 秒的时间,因此背压机制将减少后续批次的输入记录。这仅在几批之后发生,因为背压机制(也称为“PID 控制器”)需要等到第一批完成后才能使用该经验来估计下一个间隔的输入记录数。正如已经提到的,处理第一个 151200 花费的时间不止一个间隔,这意味着后续的两个间隔已经使用 maxRatePerPartition 进行了调度,而没有完成批处理间隔的经验。

这就是为什么您看到输入记录仅在第四批中减少的原因。然后,输入记录的数量仍然太多,无法在 60 秒内处理,因此作业建立了越来越多的延迟,PID 控制器(背压)最终意识到它落后于许多记录,并且正在急剧减少42 * 60 partitions * 60 seconds batch interval = 151200 records per batch 设置的最小输入记录数。在您的情况下,此值似乎设置为 2,这导致每个批次间隔 2 * 60 * 60 = 7200 条记录。

总而言之,您观察到的是预期和预期的行为。流作业需要一些批次来理解和了解它应该从 Kafka 获取多少数据以适应给定的(非灵活)批次间隔 60 秒。 无论一个批次的处理时间有多长,您的流媒体作业都会在每 60 秒的时间内提前计划下一个批次。

你可以做什么:

  • 建议将 spark.streaming.backpressure.pid.minRate 设置为实际容量的 150-200% 左右。只需让作业运行更长的时间,您就会看到估计的 100% 是多少。
  • 当您在 Kafka 中使用 60 个分区时,您需要确保数据在各个分区中均匀分布。只有这样 maxRatePerPartition 才会做你想做的事情
  • 有 60 个分区,您可以在 Spark 集群中使用 60 个核心以获得最大的消耗速度。