结构化流式流流连接

时间:2018-04-14 17:53:41

标签: apache-spark spark-structured-streaming

我使用Spark Structured Streaming 2.3有如下逻辑: 我在id上加入两个流,然后输出连接流数据。不使用水印。这是一个简单的套接字流设置。

  val df1 = spark.readStream.format("socket").option("host","localhost").option("port","5431").load()

  val df2 = df1.as[String].map(x=>x.split(","))

  val df3 = df2.select($"value"(0).as("name"),$"value"(1).cast(IntegerType).as("id"),$"value"(2).cast(TimestampType).as("ts"))

  val df1_1 = spark.readStream.format("socket").option("host","localhost").option("port","5430").load()

  val df2_1 = df1_1.as[String].map(x=>x.split(","))

  val df3_1 = df2_1.select($"value"(0).as("name"),$"value"(1).cast(IntegerType).as("id"),$"value"(2).cast(TimestampType).as("ts"))

  val joindf = df3.join(df3_1,df3("id") <=> df3_1("id"))

  val res = joindf.writeStream.outputMode("append").trigger(Trigger.ProcessingTime(15 seconds))
    .format("console").option("truncate","false").start()

  res.awaitTermination()

假设第一个触发器在两个流中包含数据:

df3:

vinyas,1,2018-03-17 09:04:21
namratha,2,2018-03-17 09:04:23
varsha,3,2018-03-17 09:04:33

df3_1:

vinyas,1,2018-03-17 09:04:21
shetty,2,2018-03-17 09:04:23
varsha,3,2018-03-17 09:04:33

我得到了预期的结果:

-------------------------------------------
Batch: 0
-------------------------------------------
+--------+---+-------------------+------+---+-------------------+
|name    |id |ts                 |name  |id |ts                 |
+--------+---+-------------------+------+---+-------------------+
|vinyas  |1  |2018-03-17 09:04:21|vinyas|1  |2018-03-17 09:04:21|
|varsha  |3  |2018-03-17 09:04:33|varsha|3  |2018-03-17 09:04:33|
|namratha|2  |2018-03-17 09:04:23|shetty|2  |2018-03-17 09:04:23|
+--------+---+-------------------+------+---+-------------------+

接下来我流数据: DF3:

shrinivas,2,2018-03-17 09:04:23

df3_1:

vidya,2,2018-03-17 09:04:23

获取输出:

-------------------------------------------
Batch: 1
-------------------------------------------
+---------+---+-------------------+------+---+-------------------+
|name     |id |ts                 |name  |id |ts                 |
+---------+---+-------------------+------+---+-------------------+
|shrinivas|2  |2018-03-17 09:04:23|shetty|2  |2018-03-17 09:04:23|
|namratha |2  |2018-03-17 09:04:23|vidya |2  |2018-03-17 09:04:23|
|shrinivas|2  |2018-03-17 09:04:23|vidya |2  |2018-03-17 09:04:23|
+---------+---+-------------------+------+---+-------------------+

如果没有4条记录而不是3条记录,有人可以解释我如何获得批处理1的结果吗?

1 个答案:

答案 0 :(得分:0)

根据官方Spark Structured Streaming Programming Guide

  

带有可选水印的内部联接

     

支持任何种类的列上的内部联接以及任何种类的联接条件。但是,随着流的运行,流状态的大小将无限期地增长,因为必须保存所有过去的输入,因为任何新输入都可以与过去的任何输入匹配。为了避免无界状态,您必须定义其他联接条件,以使无限长的旧输入不能与将来的输入匹配,因此可以从状态中清除它们。换句话说,您将必须在连接中执行以下其他步骤。

     

定义两个输入上的水印延迟,以便引擎知道输入的延迟程度(类似于流聚合)

     

定义两个输入之间的事件时间约束,以便引擎可以确定何时不需要与另一个输入匹配的一个输入的旧行(即不满足时间约束)。可以通过两种方式之一来定义此约束。

     

时间范围加入条件(例如...在leftTime到rightTime AND rightTime + INTERVAL 1 HOUR之间加入JOIN),

     

加入事件时间窗口(例如... JOIN ON leftTimeWindow = rightTimeWindow)。

从您的示例中,您可以在“追加”模式下获得正确的结果:

您在先前的批处理结果中已经有此记录:

|namratha|2 |2018-03-17 09:04:23|shetty|2 |2018-03-17 09:04:23|

我的理解是,它不应再出现在“附加模式”中。

希望有帮助!