Structured Streaming Programming Guide

概述

结构化流是一种基于Spark SQL引擎的可扩展且容错的流处理引擎。他可以像表达静态数据的批处理计算一样表达流式计算。

快速示例

监听本地netcat服务器的输入内容 实时计算每个单词出现的次数在屏幕上打印
可以通过运行下载的Spark目录下的程序直接启动 再另外启动一个netcat服务器 再服务器终端输入内容即可在控制台看见相应的输出

编程模型

结构化流中的关键思想是将实时数据流视为连续追加的表。这使得新的流处理模型非常类似于批处理模型。您将流式计算表示为静态表上的标准批处理查询,Spark将其作为无界输入表上的增量查询运行。

基本概念

将输入数据流视为“输入表”。到达流的每个数据项都像一个新行被附加到输入表。
模型对输入的查询将生成“结果表”。每个触发间隔(例如,每1秒),新行将附加到输入表,最终更新结果表。每当结果表更新时,我们都希望将更改的结果行写入外部接收器。
流程图Structured Streaming不会存储整个表,他只是从数据源逐渐取得数据,处理以更新结果,然后丢弃源数据。

使用数据集和数据资源的API

创建流式DataFrames和流式Datasets
输入源

有一些内置源。

  • 文件来源。目录中写入的文件作为数据源
  • Kafka来源。从Kafka读取源数据
  • 套接字来源
  • 速率源
流式 DataFrames/Datasets的操作
基本操作-查询 投影 聚合
case class DeviceData(device: String, deviceType: String, signal: Double, time: DateTime)

val df: DataFrame = ... // streaming DataFrame with IOT device data with schema { device: string, deviceType: string, signal: double, time: string }
val ds: Dataset[DeviceData] = df.as[DeviceData]    // streaming Dataset with IOT device data

// Select the devices which have signal more than 10
df.select("device").where("signal > 10")      // using untyped APIs   
ds.filter(_.signal > 10).map(_.device)         // using typed APIs

// Running count of the number of updates for each device type
df.groupBy("deviceType").count()                          // using untyped API

// Running average signal for each device type
import org.apache.spark.sql.expressions.scalalang.typed
ds.groupByKey(_.deviceType).agg(typed.avg(_.signal))    // using typed API

还可以将流式DataFrame / Dataset注册为临时视图,然后在其上执行SQL命令。

df.createOrReplaceTempView("updates")
spark.sql("select count(*) from updates")  // returns another streaming DF
事件时间的窗口操作(Window Operations on Event Time)

计算10分钟内的单词,每5分钟更新一次。也就是说,在10分钟窗口12:00-12:10,12:05-12:15,12:10-12:20等之间收到的单词数量。

import spark.implicits._

val words = ... // streaming DataFrame of schema { timestamp: Timestamp, word: String }

// Group the data by window and word and compute the count of each group
val windowedCounts = words.groupBy(
  window($"timestamp", "10 minutes", "5 minutes"),
  $"word"
).count()
处理延迟数据和水印

import spark.implicits._

val words = ... // streaming DataFrame of schema { timestamp: Timestamp, word: String }

// Group the data by window and word and compute the count of each group
val windowedCounts = words
    .withWatermark("timestamp", "10 minutes")
    .groupBy(
        window($"timestamp", "10 minutes", "5 minutes"),
        $"word")
    .count()
加入操作
流和静态数据连接

自Spark 2.0引入以来,Structured Streaming支持流和静态DataFrame / Dataset之间的连接(内连接和某种类型的外连接)。

val staticDf = spark.read. ...
val streamingDf = spark.readStream. ...

streamingDf.join(staticDf, "type")          // inner equi-join with a static DF
streamingDf.join(staticDf, "type", "right_join")  // right outer join with a static DF 
流和流的连接

在Spark 2.3中,我们添加了对流 - 流连接的支持,也就是说,您可以加入两个流Datasets/DataFrames.。在两个数据流之间生成连接结果的挑战是,在任何时间点,数据集的视图对于连接的两侧都是不完整的,这使得在输入之间找到匹配更加困难。从一个输入流接收的任何行都可以与来自另一个输入流的任何未来的,尚未接收的行匹配。因此,对于两个输入流,我们将过去的输入缓冲为流状态,以便我们可以将每个未来输入与过去的输入相匹配,从而生成连接结果。

流中重复数据的删除

您可以使用事件中的唯一标识符对数据流中的记录进行重复数据删除。

al streamingDf = spark.readStream. ...  // columns: guid, eventTime, ...

// Without watermark using guid column
streamingDf.dropDuplicates("guid")

// With watermark using guid and eventTime columns
streamingDf
  .withWatermark("eventTime", "10 seconds")
  .dropDuplicates("guid", "eventTime")
不支持的操作

流式DataFrames / Datasets不支持一些DataFrame / Dataset操作。其中一些如下。

  • 流数据集尚不支持多个流聚合(即流式DF上的聚合链)。
  • 流数据集不支持限制和前N行。
  • 不支持对流数据集进行不同的操作。
  • 仅在聚合和完全输出模式之后,流数据集才支持排序操作。
  • 不支持流数据集上的几种外连接类型。

此外,有一些数据集方法不适用于流数据集。它们是立即运行查询并返回结果的操作,这对流式数据集没有意义。相反,这些功能可以通过显式启动流式查询来完成。

  • count() - 无法从流式数据集返回单个计数。而是使用ds.groupBy().count()它返回包含运行计数的流数据集。

  • foreach()- 而是使用ds.writeStream.foreach(…)(见下一节)。

  • show() - 而是使用控制台接收器(参见下一节)。

如果您尝试任何这些操作,您将看到AnalysisException类似“operation XYZ is not supported with streaming DataFrames/Datasets”。虽然其中一些可能在未来的Spark版本中得到支持,但还有一些基本上难以有效地实现流数据。例如,不支持对输入流进行排序,因为它需要跟踪流中接收的所有数据。因此,这基本上难以有效执行。

启动流式查询

一旦定义了最终结果DataFrame / Dataset,必须使用返回的DataStreamWriter Dataset.writeStream()在此接口中指定以下一项或多项:

  • 输出下沉的细节:数据格式和位置等。
  • 输出模式
  • 查询名称:可选地,指定查询的唯一名称以进行标识。
  • 触发间隔:可选择指定触发间隔。
  • 检查点位置:对于可以保证端到端容错的某些输出接收器,请指定系统写入所有检查点信息的位置。
输出模式

有几种类型的输出模式。

  • Append mode (默认):这是默认模式,其中只有自上次触发后添加到结果表的新行将输出到接收器。
  • Complete mode: 每次触发后,整个结果表将输出到接收器。
  • Update mode:(自Spark 2.1.1起可用)仅将结果表中自上次触发后更新的行输出到接收器。
输出下沉接收器

有几种类型的内置输出接收器。

  • File Sink-将输出存储到目录。
`writeStream
    .format("parquet")        // can be "orc", "json", "csv", etc.
    .option("path", "path/to/destination/dir")
    .start()`
  • Kafka sink - 将输出存储到Kafka中的一个或多个主题。
writeStream
    .format("kafka")
    .option("kafka.bootstrap.servers", "host1:port1,host2:port2")
    .option("topic", "updates")
    .start()
  • Foreach接收器 - 对输出中的记录运行任意计算。
writeStream
    .foreach(...)
    .start()
  • 控制台接收器(用于调试) - 每次触发时将输出打印到控制台/标准输出。支持Append和Complete输出模式。这应该用于低数据量的调试目的,因为在每次触发后收集整个输出并将其存储在驱动程序的内存中。
writeStream
    .format("console")
    .start()
  • 内存接收器(用于调试) - 输出作为内存表存储在内存中。支持Append和Complete输出模式。这应该用于低数据量的调试目的,因为整个输出被收集并存储在驱动程序的内存中。
writeStream
    .format("memory")
    .queryName("tableName")
    .start()
使用Foreach和ForeachBatch

oreach 允许每行上的自定义写入逻辑,foreachBatch允许在每个微批量的输出上进行任意操作和自定义逻辑。

ForeachBatch

foreachBatch(…)允许您指定在流式查询的每个微批次的输出数据上执行的函数。它需要两个参数:DataFrame或Dataset,它具有微批次的输出数据和微批次的唯一ID。

streamingDF.writeStream.foreachBatch { (batchDF: DataFrame, batchId: Long) =>
  // Transform and write batchDF 
}.start()
foreach

如果foreachBatch不是一个选项(例如,相应的批处理数据写入器不存在,或连续处理模式),那么您可以使用表达自定义编写器逻辑foreach。具体来说,可以通过将其划分为三种方法表达数据写入逻辑:open,process,和close。
在Scala中,您必须扩展类ForeachWriter:

streamingDatasetOfString.writeStream.foreach(
  new ForeachWriter[String] {

    def open(partitionId: Long, version: Long): Boolean = {
      // Open connection
    }

    def process(record: String): Unit = {
      // Write string to connection
    }

    def close(errorOrNull: Throwable): Unit = {
      // Close the connection
    }
  }
).start()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Structured Streaming 是 Apache Spark 的一种流式处理引擎,它可以帮助我们对流式数据进行转换、处理和聚合。Structured Streaming 使用了基于 SQL 的语法,因此我们可以使用熟悉的 SQL 语句来对流式数据进行操作。例如,我们可以使用以下 SQL 语句对流式数据进行过滤: ``` SELECT * FROM stream WHERE value > 5 ``` 或者使用以下 SQL 语句对流式数据进行分组并计算每组的平均值: ``` SELECT key, AVG(value) FROM stream GROUP BY key ``` Structured Streaming 还支持联机处理,即可以对流式数据进行实时处理,并将结果实时输出。这使得我们可以使用 Structured Streaming 实现各种实时数据处理任务,如实时统计、实时分析等。 ### 回答2: 结构化流式处理(Structured Streaming)是一种用于处理实时数据的数据处理引擎。它允许开发人员使用SQL查询实时流数据,无需编写复杂的流式处理程序。Structured Streaming SQL是一种使用SQL语句对实时数据进行查询和操作的方式。 Structured Streaming SQL可以通过Spark SQL的语法和功能来处理实时数据。它可以将实时数据以表的形式表示,并且支持标准SQL查询操作,例如选择、过滤、聚合和连接操作。在Structured Streaming SQL,开发人员可以使用常见的SQL函数和操作符来处理实时数据。 Structured Streaming SQL还支持时间窗口操作,可以通过指定窗口长度和滑动步长来对实时数据进行分组和聚合。此外,Structured Streaming SQL还支持流-静态表连接,可以将实时流数据与静态数据表进行关联操作,以便获得更丰富的分析结果。 Structured Streaming SQL的一个主要特点是其容错性和弹性。当发生故障或数据丢失时,Structured Streaming可以自动从上次检查点恢复,并且能够动态调整计算资源以适应数据的变化。 总而言之,Structured Streaming SQL提了一种简单、灵活且易于使用的方式来处理和分析实时数据。通过使用SQL语句,开发人员可以更快地构建和迭代实时数据处理应用程序,从而更好地理解和利用实时数据的价值。 ### 回答3: Structured StreamingSpark的一种流处理方式,可以使用SQL语句来对流式数据进行处理和分析。它使用了DataFrame和Dataset这两种抽象概念,提了与传统批处理相似的编程模型,可以方便地进行流处理任务。 与传统的流处理方式相比,Structured Streaming具有以下特点: 1. 连接机制:Structured Streaming可以连接各种输入源和输出目标,如Kafka、消息队列等,方便处理不同来源和去向的数据。 2. 强大的API支持:Structured Streaming了丰富的API,可以通过SQL语句或DataFrame/Dataset API来执行流处理任务,使得开发人员可以使用熟悉的SQL语言进行流处理操作。 3. 实时处理:Structured Streaming支持实时处理,可以以毫秒级的延迟来处理数据,使得我们能够实时处理数据流并及时生成结果。 4. 容错性:Structured Streaming具有高度的容错性,能够自动处理失败和恢复。它使用了Spark的弹性分布式数据集(RDD)来进行数据处理,一旦发生故障,它可以自动从上一次处理的结果继续进行处理。 5. 一致性:Structured Streaming保证了事件的顺序和一致性,保证数据的完整性和正确性。 6. 扩展性:Structured Streaming具有良好的扩展性,可以根据实际需求进行水平扩展,以满足大规模数据处理的需求。 结构化流处理SQL的使用可以极大地简化流处理任务的编写和维护,使得开发人员能够更加专注于业务逻辑的实现。通过使用结构化流处理SQL,我们可以方便地进行各种流处理操作,包括过滤、转换、聚合以及窗口操作等,同时可以借助Spark的优化能力来提高处理性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值