重跑的幂等设计

任务重跑必须产出相同结果:优先“分区覆盖写”,其次“按主键 upsert”,再次“写临时表后切换”;流水账式累加(+=、count++)是最容易出错的模式。

幂等重跑是什么

幂等的含义是「同一任务跑一次和跑十次,结果一样」。这在数据管道里不是可选项:上游补数、口径调整、任务失败重试都会触发重复运行,如果任务自带累加逻辑,重跑就等于把数据翻倍。最稳妥的实现方式是输出按分区覆盖写,其次是按主键 upsert,再次是写临时表后原子切换;最危险的是依赖上次运行状态的累加(+=、count++ 之类)。

基本信息

首选方案输出按分区覆盖(INSERT OVERWRITE PARTITION)
次选方案按主键 upsert / MERGE
兜底方案写临时表后切换或改名
应避免依赖上次运行状态的累加逻辑
前置条件输出表有明确的分区键或主键
配套要求重跑范围可界定、可观测、可回滚

分区覆盖重跑

分区覆盖重跑
-- 重跑 2026-10-11 分区:先写该分区,覆盖旧结果
INSERT OVERWRITE TABLE ads_sales_daily PARTITION (dt = '2026-10-11')
SELECT dt, channel, SUM(amount)
FROM dwd_order WHERE dt = '2026-10-11'
GROUP BY dt, channel;

典型使用场景

  • 上游断数后补数:只重跑受影响分区,结果与首次运行一致
  • 口径变更重刷:历史区间按新逻辑覆盖,不残留旧口径数据
  • 失败重试:调度器自动重试时不会产生重复数据
  • 跨天累计指标:改用「按天快照 + 查询时累加」,避免在表里维护累计值
  • 消息消费:下游按主键 upsert,重复投递不会产生重复行

写入方式对照

方式幂等性注意
分区覆盖写好必须带分区条件,防止误删历史
主键 upsert好主键取值要稳定唯一
拼接追加差重跑必然产生重复
读旧值再加差并发与重跑都会放大误差
写临时表再切换好切换动作本身要原子
重跑前先确认输出分区不会被其他并发任务覆盖;跨任务写同一分区时加调度依赖或互斥。
所谓「临时表 + 切换」在对象存储上不是原子操作:改名可能退化成拷贝,切换期间会出现半成品数据被读到,需要下游按目录版本或元数据指针读取。

易错点

  • 全表覆盖(不带分区)重跑会把历史数据清空,SQL 评审要专门检查
  • 用状态表记录进度的任务,重跑时要能回退状态,否则进度永远对不上
  • 只在任务里做去重,输入本身重复时下游仍会看到重复
  • 临时表与目标表共用同一目录命名规则,并发重跑时互相污染
  • 把「重跑后校对行数」当可选项,实际上没有核对就无法确认幂等是否成立

数据来源与参考

  • Apache Hive LanguageManual DML(INSERT OVERWRITE 语义)
  • 行业通用幂等重跑实践
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌