Spark结构化流状态作业的重处理策略

时间:2019-08-07 08:26:43

标签: apache-spark spark-structured-streaming

我目前正在研究如何通过此代码实现可维护的有状态结构化流作业:

val inputDataFrame = sparkSession.readStream.format("kafka")
val query = inputDataFrame.
  // ...
  .groupByKey(row => row.getAs[Long]("user_id"))
  .mapGroupsWithState(mapLogsToIntermediarySessions())

val writeQuery = query.writeStream
    .foreachBatch(writeBatch(outputDir, sparkSession) _).start()

def writeBatch(outputDir: String, sparkSession: SparkSession)(batchDataset: Dataset[SessionIntermediaryState], batchId: Long) = {
  import sparkSession.implicits._
  batchDataset.filter(state => !state.isActive)
    .flatMap(state => state.toSessionOutputFormat)
    .json(outputDir)
}

我的担心与后处理有关。

如果数据源可以像Apache Kafka一样重播,则不会出现问题,因为即使丢失了检查点信息,我们也可以在分区偏移量内移动。

状态存储并不那么容易。该商店将仅保留X个最新状态,其中X配置为spark.sql.streaming.minBatchesToRetain条目,其默认值为100。现在,如果您在星期四部署了错误版本,并且仅在下周一发现该错误,则可能花费的时间超过重新处理逻辑中的第100个状态版本。很好,您仍然可以将minBatchesToRetain配置为与允许的重新处理延迟相对应的很大数字。

但是,另一方面,我想知道是否有更好的方法来解决这个问题?您如何确保可以轻松地重新处理有状态的流作业?

我其他的选择是:

  • 使用仅在作业外清除的仅附加状态存储,例如DynamoDB TTL属性
  • 与其生成最终输出到S3,而是在其中写入每个状态更新,然后找到一种将状态加载到应用程序的方法

0 个答案:

没有答案