1、数据回填概述:什么是数据回填、回填与补数的区别、回填的典型业务场景

大家好,我是老张。做了快十年调度系统,今天咱们聊聊数据回填。

说实话,刚入行那会儿我也分不清回填和补数有什么区别。直到有一次凌晨三点被电话叫醒,说离线数仓的指标全乱了……嗯,那次之后我才真正搞明白这两个概念。

1.1 什么是数据回填

数据回填,说白了就是把历史时间段里缺失或错误的数据,重新计算并写回去。

举个例子:你每天凌晨跑一次离线ETL,计算前一天的销售总额。结果某天发现上游业务表少传了2小时的数据。等数据补上来之后,你需要把那天重新算一遍,把正确的结果覆盖回去——这就是回填。

核心特征:

  • 操作对象是历史分区(昨天、前天、甚至上个月)
  • 触发原因是数据质量或链路异常
  • 执行结果是覆盖已有数据

我在项目中遇到过最典型的场景:实时数仓的Kafka链路挂了6小时,恢复后需要把这段时间的流式数据重新从ODS层拉取、计算、写入DWS层。那次回填涉及200多个任务,调度依赖关系像蜘蛛网一样复杂。

1.2 回填与补数的区别

很多同学把回填和补数混为一谈。我刚开始也这样,直到被架构师怼了一次才记住。

维度 数据回填 数据补数
触发时机 数据已产出,但质量不合格 数据从未产出过
操作范围 覆盖已有分区 新增缺失分区
调度策略 需要清理旧数据再写入 直接追加写入
典型场景 上游数据延迟、逻辑变更 新接入数据源、历史初始化
风险等级 高(可能影响下游依赖) 中(通常无覆盖风险)

举个例子你就明白了:

  • 补数:你新接了一个支付渠道,需要把过去3个月的历史数据拉回来。这些分区之前不存在,直接写进去就行。
  • 回填:支付渠道的数据一直有,但昨天发现某个字段解析错了。你需要把昨天的分区删掉,重新跑一遍任务,再把正确结果写回去。

避坑指南:我曾经在回填时忘了清理旧分区,结果新旧数据混在一起,下游报表出现了"数据跳变"。后来我养成了一个习惯:回填任务的第一步必须是TRUNCATE或DELETE目标分区。

1.3 回填的典型业务场景

回填不是天天发生,但一旦发生,往往都是紧急情况。我总结了两大类最常见的场景。

场景一:离线数仓回填

离线数仓是回填的"重灾区"。为什么?因为链路长、依赖多、任何一个环节出问题都会导致数据异常。

  • 上游数据延迟:业务库凌晨3点才把前一天的全量数据推过来,但你的ETL任务凌晨1点就跑完了。怎么办?等数据到了之后回填。
  • 逻辑变更:产品经理说"昨天的转化率口径不对,需要按新规则重算"。这时候你需要把昨天的分区全部回填。
  • 数据质量修复:发现某个字段有NULL值,或者join丢了数据。定位问题后,需要回填受影响的时间段。

我的经验:离线数仓回填最怕的是"级联回填"。你回填了DWD层,DWS层和ADS层也得跟着回填。所以调度系统必须支持下游依赖自动触发,否则人工操作容易漏掉。

场景二:实时链路修复

实时链路出问题,回填的难度比离线大得多。因为实时数据是流式的,没有"分区"的概念。

  • Kafka消息积压或丢失:实时ETL任务挂了2小时,恢复后需要把这2小时的流式数据重新消费一遍。
  • 状态不一致:Flink任务重启后,状态后端的数据丢了。需要从Checkpoint或Savepoint恢复,同时回填丢失时间段的数据。
  • 实时转离线:有些场景是"实时+离线"双链路。实时链路挂了,离线链路还在跑。等实时链路恢复后,需要把离线数据回填到实时表中。

我记得有一次,实时数仓的Flink任务因为OOM挂了。恢复之后发现状态全丢了,窗口聚合结果全部归零。最后只能从Kafka重置offset到故障时间点,重新消费一遍数据。那次回填跑了整整8个小时。

1.4 回填的核心流程

不管什么场景,回填的流程都差不多。我画了一张图,你看一眼就明白了。

数据回填核心流程 1. 发现问题 2. 定位影响范围 3. 清理旧数据 4. 重新计算并写入 常见触发原因 • 上游数据延迟 • 逻辑变更 • 数据质量异常 关键注意事项 • 先清理再写入 • 级联触发下游 • 记录回填日志 回填 vs 补数 • 回填:覆盖已有数据 • 补数:新增缺失数据 • 回填风险更高

这个流程看起来简单,但实际落地时坑很多。比如第三步"清理旧数据",如果你用的是Hive分区表,直接ALTER TABLE DROP PARTITION就行。但如果是Kudu或ClickHouse,清理方式完全不同。

回填的黄金法则:

  1. 先清理,再写入——避免数据重复
  2. 记录回填日志——方便追溯和回滚
  3. 通知下游依赖——防止下游基于错误数据做计算

1.5 小结

数据回填是调度系统里最考验设计能力的场景之一。它不像日常调度那样按部就班,而是需要处理"历史数据修正"这个特殊需求。

记住三个关键点:

  • 回填是覆盖,补数是新增,别搞混
  • 离线数仓回填关注分区管理,实时链路回填关注状态恢复
  • 回填一定要先清理再写入,这是血的教训