我使用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的结果吗?
答案 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|
我的理解是,它不应再出现在“附加模式”中。
希望有帮助!