检查点解决什么
Spark 检查点把运行状态与血缘信息持久化到可靠存储。结构化流任务必须配置 checkpointLocation 才能记录处理进度与状态,故障重启后可续跑;批任务调用 checkpoint 则把 RDD 血缘截断,避免血统过长导致的重算与栈溢出。两者名称相同,作用与位置完全不同。
基本信息
| 流检查点 | 记录 offset、状态、元数据,供重启续跑 |
|---|---|
| 批检查点 | setCheckpointDir 指定目录,配合 rdd.checkpoint 截断血缘 |
| 存储位置 | 需要可靠共享存储,如 HDFS 或对象存储 |
| 版本兼容 | 升级 Spark 大版本后旧检查点可能不兼容,需评估重建 |
| 清理 | 流检查点需定期清理历史版本文件 |
典型使用场景
- 流任务故障恢复:重启后从上次处理位置继续,避免重复消费
- 带状态的流计算:窗口聚合、去重、自定义状态算子必须靠检查点保存状态
- 批任务血缘过长:迭代计算或反复 union 后先 checkpoint 再触发计算
- 任务迁移:集群或目录调整时评估检查点迁移方案
- 调优与排障:通过检查点目录判断任务实际处理进度
批检查点用法
批检查点用法
// 指定可靠的检查点目录,集群模式下不能用本机临时目录
spark.sparkContext.setCheckpointDir("hdfs:///tmp/checkpoint")
// 先重分区再 checkpoint,避免产生大量小文件
val df = spark.table("dwd_trade_order_di").repartition(64).checkpoint()
df.count() // checkpoint 是懒执行,必须触发一次 action 才会真正落盘
// 流任务:在 writeStream 上指定检查点位置,目录确定后不要随意更换
// .option("checkpointLocation", "hdfs:///user/dw/chk/order_stream")检查点内容读法
| 内容 | 含义 | 异常表现 |
|---|---|---|
| offsets | 已处理的数据位置 | 缺失会导致任务从头或按起始配置重放 |
| commits | 已提交的批次记录 | 损坏会让任务无法判断断点,只能重建目录 |
| state | 状态算子的中间结果 | 丢失则状态归零,去重与聚合结果出错 |
| metadata | 版本与查询配置信息 | 与当前 Spark 版本不匹配时启动即失败 |
批检查点主要作用是切断血缘与复用中间结果,它把数据写到指定目录,会额外占用存储;只在一段计算会被多次引用或血统确实过长时才值得引入。
流任务的检查点目录一旦更换,等价于一个全新任务:要么重跑全部历史数据,要么从头开始消费,可能引发下游重复计算。目录要与业务数据分区存放,避免清理脚本误删。