订阅更新

从Savepoint恢复后数据重复了——Savepoint和Checkpoint有什么区别?

Flink手册 第 14 题 约 3 分钟读完

本文目录
  1. 先说结论
  2. 典型使用场景
  3. 为什么从Savepoint恢复后会数据重复?
  4. 实战经验
  5. 总结

先说结论

维度CheckpointSavepoint
触发方式自动定期触发手动触发(flink savepoint命令)
用途故障恢复(自动)作业升级、近移、调整并行度(手动)
生命周期作业结束后自动清理(默认)永久保存,手动删除
存储格式特定于后端(RocksDB原生格式)标准化格式(跨版本兼容)
增量支持支持增量Checkpoint不支持(每次全量)

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

Savepoint和Checkpoint是Flink里最容易混淆的两个概念。它们的技术原理几乎一样(都是状态快照),但用途和生命周期完全不同。而且很多人从Savepoint恢复后遇到“数据重复”的问题,今天把这些讲清楚。

典型使用场景

场景一:作业升级(最常见)

你修改了作业的逻辑需要重新部署。流程:

  1. 手动触发Savepoint:flink savepoint hdfs:///savepoints/
  2. 停止旧作业:flink cancel
  3. 从Savepoint启动新作业:flink run -s hdfs:///savepoints/savepoint-xxx new-job.jar

场景二:调整并行度

发现作业反压需要加并行度。同样是Savepoint→停止→修改并行度→从Savepoint重启。

为什么从Savepoint恢复后会数据重复?

这是最常见的坑。原因是:

Savepoint只保存了Flink的状态,不保存Kafka的Offset提交状态。

具体来说:Savepoint里记录了Kafka的Offset(比如读到了offset=1000)。从Savepoint恢复后,Flink会从offset=1000重新消费。但如果Sink已经把offset=900-1000的数据写入了目标存储(而且Sink没有事务保证),那这部分数据就会被重复处理。

解决方案:

  1. Sink支持事务(如Kafka Exactly-Once Sink)→ 不会重复
  2. Sink支持幂等写入(如写入时带唯一键,重复写入也不会产生重复数据)→ 效果上不重复
  3. Sink不支持事务也不幂等(如纯追加写文件)→ 会重复,只能接受或下游去重

实战经验

我在元宇宙社交App时建立的Savepoint规范:

  1. 每次作业升级前必须先触发Savepoint
  2. Savepoint保留最近3个版本,方便回滚
  3. 所有Sink都必须支持幂等写入(带业务唯一键)
  4. 升级后观察30分钟确认无异常再删除旧Savepoint

总结

Checkpoint是自动故障恢复,Savepoint是手动作业升级。Savepoint恢复后数据重复的根因是Sink不支持事务/幂等。面试时能说清楚两者区别、Savepoint的使用流程、以及“为什么恢复后会重复”的原理和解决方案,就很有深度。

下一篇聊一个非常实用的话题:Flink读写Kafka的Connector配置和踩坑经验。

你们生产环境用Savepoint的频率是多少?评论区聊聊~

关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长

刷题进度保存在当前浏览器