我目前正在研究如何通过此代码实现可维护的有状态结构化流作业:
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属性