结构化流媒体:水印与精确一次的语义

时间:2017-08-08 22:42:01

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

编程指南说结构化流媒体使用适当的源/接收器确保端到端一次性语义。

但是,当作业崩溃并且我们应用了水印时,我不理解它是如何工作的。

下面是我目前想象它如何工作的一个例子,请纠正我对我误解的任何观点。提前谢谢!

示例:

Spark Job:在每个1小时的窗口中计算#个事件,使用1个小时的水印。

消息:

  • A - 时间戳上午10点
  • B - 时间戳上午10点10分
  • C - 时间戳上午10:20
  • X - 时间戳12pm
  • Y - 时间戳下午12:50
  • Z - 时间戳晚上8点

我们开始这项工作,从源头读取A,B,C,并在我们将它们写入我们的水槽之前上午10:30崩溃。

下午6点,作业恢复正常,并且知道使用保存的检查点/ WAL重新处理A,B,C。 10-11am窗口的最终计数是3。

接下来,它会并行读取来自Kafka,X,Y,Z的新消息,因为它们属于不同的分区。首先处理Z,因此最大事件时间戳设置为晚上8点。当作业读取X和Y时,它们现在位于水印之后(晚上8点 - 1小时=晚上7点),因此它们将作为旧数据丢弃。最终计数是1到8-9pm,并且该作业没有报告12-1pm窗口的任何内容。我们丢失了X和Y的数据。

---结束示例---

这种情况是否准确? 如果是这样,1小时水印可能足以处理从Kafka-Sspark正常流动时的延迟/无序数据,但是当火花作业停止/ Kafka连接长时间丢失时则不会。避免数据丢失的唯一选择是使用比你预期的工作更长的水印吗?

1 个答案:

答案 0 :(得分:1)

  

首先处理Z,因此最大事件时间戳设置为晚上8点。

这是对的。即使可以首先计算Z,也可以从当前查询迭代中的最大时间戳中减去水印。这意味着08:00 PM将被设置为我们从中减去水印时间的时间,这意味着将丢弃12:00和12:50。

From the documentation

  

对于从时间T开始的特定窗口,引擎将保持状态并允许延迟数据更新状态直到(引擎看到的最大事件时间 - 晚期阈值> T)

  

避免数据丢失的唯一选择是使用比您预期的工作时间更长的水印

不一定。让我们假设您将每个Kafka查询的最大数据量设置为100个项目。如果您阅读小批量,并且从每个分区串行读取,则每个批次的每个最大时间戳可能不是代理中最新消息的最长时间,这意味着您不会丢失这些消息。