Spark每日半小时(28)——结构化流式编程:概览、示例

概览

结构化流是一种基于Spark SQL引擎的可扩展且容错的流式处理引擎。我们可以像表达静态数据的批处理计算一样表达流式计算。Spark SQL引擎将负责逐步和连续地运行它,并在流数据持续到达时更新最终结果。我们可以使用Scala,Java,Python或R中地Dataset/DataFrame API来表示流聚合,事件事件窗口,流到批处理连接等。计算在同一优化的Spark SQL引擎上执行。最后,系统通过检查点和预读日志确保端到端的一次性容错保证。简而言之,结构化流传输提供快速,可扩展,容错,恰好一次的流处理,而无需用户推理流式传输。

在内部,默认情况下,结构化流式查询使用micro-batch处理引擎,该引擎将数据流作为一系列小批量作业处理,从而实现低至100毫秒的段端到端延迟和完全一次的容错保证。但是,自Spark 2.3以来,我们引入了一种成为连续处理的新型低延迟处理模式,它可以实现低至1毫秒的端到端延迟,并且具有至少一次保证。无需更改查询中的Dataset/DataFrame此操作,我们就可以根据应用程序要求选择模式。

该篇开始,将进入结构化流式处理模块。我将完成编程模型和API,并将解释大多使用默认的micro-batch处理模式的概念,再后来讨论连续处理模式。首先,我们从一个结构化流式查询的简单示例开始。

示例

假设我们希望维护从监听TCP socket的数据服务器接收的文本数据的运行字数。让我们来看看如何使用Structured Streaming来实现该需求。

按照实现步骤,首先,我们必须导入必要的类并创建一个本地SparkSession,这时与Spark相关的所有功能的起点。

    SparkSession spark = SparkSession
      .builder()
      .appName("JavaStructuredNetworkWordCount")
      .getOrCreate();

接下来,将创建一个流式DataFrame,它表示从监听localhost:9999的服务器接收的文本数据,并转换DataFrame以计算字数。

    // Create DataFrame representing the stream of input lines from connection to host:port
    Dataset<Row> lines = spark
      .readStream()
      .format("socket")
      .option("host", host)
      .option("port", port)
      .load();

    // Split the lines into words
    Dataset<String> words = lines.as(Encoders.STRING()).flatMap(
        (FlatMapFunction<String, String>) x -> Arrays.asList(x.split(" ")).iterator(),
        Encoders.STRING());

    // Generate running word count
    Dataset<Row> wordCounts = words.groupBy("value").count();

这个lines的DataFrame表示包含流文本数据的无界表。此表包含一个列明为“value”的字符串,并且流式文本数据中的每一行都成为表中的一行。注意,由于我们只是设置转换,并且尚未启动它,因此目前没有接收任何数据。接下来,我使用了lines.as(Encoders.STRING())将DataFrame转换为String格式的数据集,以便我们可以应用flatMap操作将每行拆分为多个单词。结果words数据集包含所有单词。最后,通过对words数据集中的唯一值进行分组并对其进行计数来定义DataFrame类型的wordCounts。注意,这是一个流式DataFrame,它表示流的运行字数。

现在已经设置了关于流数据的查询。剩下的就是实际开始接收数据并计算计数。为此,我们将其设置为outputMode("complete")每次更新时将完整的计数集(指定者)打印到控制台。然后使用启动流式计算的start()方法。

    // Start running the query that prints the running counts to the console
    StreamingQuery query = wordCounts.writeStream()
      .outputMode("complete")
      .format("console")
      .start();

    query.awaitTermination();

执行此代码后,流式计算将在后台启动。该query对象是该活动流式查询的对象,我们决定等待查询终止,awaitTermination()方法以防止再查询出于活动状态时推出该进程。

要实际执行此示例代码,我们可以再自己的Spark应用程序中编译代码,或者只需要下载Spark后运行该示例。后者需要使用Netcat(在大多数类Unix系统中找到的小程序)作为数据服务器运行

$ nc -lk 9999

然后在不同终端中,可以使用启动示例

$ ./bin/run-example org.apache.spark.examples.sql.streaming.JavaStructuredNetworkWordCount localhost 9999

然后,在运行netcat服务器的终端中键入的任何行将被计数并每秒在屏幕上打印,如下:

# TERMINAL 2: RUNNING JavaStructuredNetworkWordCount

$ ./bin/run-example org.apache.spark.examples.sql.streaming.JavaStructuredNetworkWordCount localhost 9999

-------------------------------------------
Batch: 0
-------------------------------------------
+------+-----+
| value|count|
+------+-----+
|apache|    1|
| spark|    1|
+------+-----+

-------------------------------------------
Batch: 1
-------------------------------------------
+------+-----+
| value|count|
+------+-----+
|apache|    2|
| spark|    1|
|hadoop|    1|
+------+-----+
...

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值