Structured Streaming《编程模型》

Structured Streaming 的核心思想是将实时数据流看作数据在不断追加的表。这种思想促生了一种新的,和批处理模型非常类似的流处理模型。您可以像表示静态数据标准批查询一样表示流计算。Spark 会在这个无界表上运行增量查询。

目录

1. 基本概念

2. 事件时间和迟到数据处理

3. 容错机制


1. 基本概念

如果把输入流看作是“Input Table”,那么流中到达的每个数据元素都像是添加到 Input Table中的一行新数据。

 输入表上的查询会产生一个 “Result Table”。每个触发间隔中(假设1s一次),新的行都会被追加到 Input Table,最终会更新 Result Table。每当result table有更新时,我们会想把更新后的结果行写出到外部sink.

 图中的 Output代表输出到外部存储的数据。这个输出有三种模式:

  • Complete Mode:输出所有结果

  • Append Mode:只输出当前批次中处理的结果(未和之前的结果合并)

  • Update Mode:只输出Result Table中值有变化的行。

请注意:每种输出模式只适用于特定类型查询,这些稍后再讨论

为了阐述这个模型的作用,让我们来深入理解下前面的入门示例。第一个 DataFrame lines是 input table,最后一个DataFrame wordcounts 是 result table。需要注意的是,在 lines DataFrame 流上查询产生的 wordCounts和在静态数据上执行的查询结果是一致的。然而,当查询开始后,Spark会不断的检查是否有新数据到来,如果有新数据,Spark会运行一个增量的查询,这个查询会结合之前的运行结果和新到的数据来计算更新后的结果:

请注意:Structured Streaming不会持久化整个输入表。它只会读取流数据中的最新数据,增量处理后更新结果,随后便会无视源数据。它只会保留更新结果需要用到的最少量中间态数据。

这个模型和很多其他的流处理引擎有很大不同。很多流处理系统要求用户自己维护运行时聚合,这就需要深究容错和数据一致性。而在这个模型中,当有新数据时Spark会负责更新结果,这就使得用户从容错和数据一致性中得到解放。

作为示例,让我们来看一下这个模型是如何处理基于事件时间的计算和迟到数据的。

2. 事件时间和迟到数据处理

事件时间是嵌在数据自身的时间。对很多应用来说,您可能会希望使用这个事件时间。比如说,如果您想知道一个物联网设备每分钟产生的事件数,那么您可能会想使用这个数据产生的时间(也就是事件时间),而不是Spark接收到他们的时间。事件时间在这个模型中得到了自然表达 -- 设备产生的每个事件都是表中的一行数据,每个事件时间都是行中的一列。这就使得窗口聚合变成一种作用在事件时间列上的特殊分组聚合(每个时间窗口是一个group,每一行属于多个窗口/groups)。因此这种基于事件时间窗口的聚合查询可以一同定义在静态数据集和流数据上,使得用户的生活更容易 ^_^。

此外,这个模型可以轻松的处理比预期时间(基于事件时间)晚到的数据。因为Spark负责更新Result Table,所以Spark对有新数据到达时更新旧的聚合结果和删除旧聚合来限制中间态数据大小有完全控制权。自Spark2.1开始,Spark还提供了水印功能,它允许用户指定迟到数据的阈值,使得引擎可以根据这个阈值清理旧的状态数据。这些内容将在窗口操作中详细阐述。

3. 容错机制

端对端exactly-once传输语义是Structured Streaming设计背后的目标之一。为了达到这个目标,Spark设计了Structured Streaming source,sinks以及可以可靠追踪处理过程的执行引擎,这样Spark就能通过重启/或重计算来处理各种失败。Spark假设每种streaming source都有offset(像kafka offsets或Kinesis sequence numbers那样),以此来标记stream的读取位置。处理引擎使用检查点和WAL来记录每个批次中处理的数据的offset范围。streaming sink被设计成重复处理幂等。这样,使用可重放source,幂等sink,Structured Streaming 在任何失败下都能保证端对端exactly-once语义。

猜你喜欢

转载自blog.csdn.net/Mathieu66/article/details/83658235