Apache spark 结构化流如何确保文件接收器的一次性写入语义?
我正在为spark structured streaming编写一个存储写入程序,它将对给定的数据帧进行分区,并写入不同的blob存储帐户。spark文档说,它确保了文件接收器的Apache spark 结构化流如何确保文件接收器的一次性写入语义?,apache-spark,spark-structured-streaming,Apache Spark,Spark Structured Streaming,我正在为spark structured streaming编写一个存储写入程序,它将对给定的数据帧进行分区,并写入不同的blob存储帐户。spark文档说,它确保了文件接收器的精确一次语义,但还说,只有当源代码可重新播放且接收器为幂等时,精确一次语义才可能 如果我用拼花格式写,blob存储是幂等水槽吗 另外,如果我正在执行streamingDF.writestream.foreachbatch(…在此处写入DF…).start(),行为将如何改变?它还能保证一次语义吗 可能重复: 更新#1:类
精确一次
语义,但还说,只有当源代码可重新播放且接收器为幂等时,精确一次语义才可能
output
.writeStream
.foreachBatch((df: DataFrame, _: Long) => {
path = storagePaths(r.nextInt(3))
df.persist()
df.write.parquet(path)
df.unpersist()
})
微间歇流处理
我假设问题是关于微批量流处理(不是连续流处理)
基于可用的和提交的偏移量内部注册表(对于当前流执行,也称为runId
)以及常规检查点(在重新启动期间保持处理状态),保证语义的精确性
只有当源是可重新播放的,而接收器是幂等的时,才可能使用一次语义
任何已经处理但未在内部正确记录的内容(见下文)都可以重新处理:
- 这意味着流查询中的所有流源都应可重新播放,以允许轮询曾经请求的数据
- 这也意味着接收器应该是幂等的,因此可以再次添加已成功处理并添加到接收器的数据,因为在结构化流管理将数据(偏移量)记录为已成功处理(在检查点)之前发生了故障
MicroBatchExecution
将偏移量提交给预写日志(WAL),并将以下信息消息打印到日志:
批次[currentBatchId]的已提交偏移量。元数据[offsetSeqMetadata]
流式查询(微批处理)仅在有新数据可用(基于偏移量)或上次执行需要另一个微批处理进行状态管理时执行
在addBatch阶段,MicroBatchExecution
请求唯一的Sink
或StreamWriteSupport
处理可用数据
一旦微批处理成功完成,MicroBatchExecution
将可用的偏移量提交到提交检查点,并且认为偏移量已经处理
MicroBatchExecution
将以下调试消息打印到日志:
已完成批次[currentBatchId]
微间歇流处理
我假设问题是关于微批量流处理(不是连续流处理)
基于可用的和提交的偏移量内部注册表(对于当前流执行,也称为runId
)以及常规检查点(在重新启动期间保持处理状态),保证语义的精确性
只有当源是可重新播放的,而接收器是幂等的时,才可能使用一次语义
任何已经处理但未在内部正确记录的内容(见下文)都可以重新处理:
- 这意味着流查询中的所有流源都应可重新播放,以允许轮询曾经请求的数据
- 这也意味着接收器应该是幂等的,因此可以再次添加已成功处理并添加到接收器的数据,因为在结构化流管理将数据(偏移量)记录为已成功处理(在检查点)之前发生了故障
MicroBatchExecution
将偏移量提交给预写日志(WAL),并将以下信息消息打印到日志:
批次[currentBatchId]的已提交偏移量。元数据[offsetSeqMetadata]
流式查询(微批处理)仅在有新数据可用(基于偏移量)或上次执行需要另一个微批处理进行状态管理时执行
在addBatch阶段,MicroBatchExecution
请求唯一的Sink
或StreamWriteSupport
处理可用数据
一旦微批处理成功完成,MicroBatchExecution
将可用的偏移量提交到提交检查点,并且认为偏移量已经处理
MicroBatchExecution
将以下调试消息打印到日志:
已完成批次[currentBatchId]
使用foreachBatch时,spark只保证foreachBatch只调用一次。但若在foreachBatch执行期间出现异常,spark将尝试为同一批再次调用该异常。在这种情况下,如果存储到多个存储器,并且在存储过程中出现异常,则可能会出现重复。 因此,您可以在存储期间手动处理异常,以避免重复
在我的实践中,如果需要存储到多个存储并使用支持提交的datasource api v2,我创建了自定义接收器。使用foreachBatch时,spark只保证foreachBatch只调用一次。但若在foreachBatch执行期间出现异常,spark将尝试为同一批再次调用该异常。在这种情况下,如果存储到多个存储器,并且在存储过程中出现异常,则可能会出现重复。 因此,您可以在存储期间手动处理异常,以避免重复 在我的实践中