3、补数范围定义:时间范围补数、分区补数、表级补数、任务级补数

补数范围怎么定?这是设计补数机制时第一个要拍板的事。

我见过不少团队,一上来就写死一个「重跑昨天数据」的逻辑。结果业务说「我要补上个月的数据」,运维说「我只想重跑某个坏掉的分区」,老板说「整个表数据都不对,给我全量重来」——好嘛,一个补数接口根本不够用。

所以,补数范围必须分层设计。我个人习惯把它拆成四个维度:时间范围、分区、表级、任务级。下面一个个说。

3.1 时间范围补数

这是最常用的补数方式。说白了,就是指定一个时间窗口,把窗口内的数据重新跑一遍。

时间范围补数通常包含三个参数:

  • 开始时间(biz_date_from)
  • 结束时间(biz_date_to)
  • 时间粒度(如天、小时、分钟)

举个例子:

{
  "type": "time_range",
  "biz_date_from": "2024-01-01",
  "biz_date_to": "2024-01-10",
  "granularity": "day"
}

这个配置的意思是:补 2024-01-01 到 2024-01-10 共 10 天的数据,每天作为一个独立补数单元。

我的经验:时间范围补数最容易踩的坑是「时区问题」。我曾经遇到一个项目,调度系统用的 UTC 时间,业务库用的东八区。补数时差了 8 个小时,数据对不上。后来我强制要求所有补数参数统一用业务时间,系统内部再转 UTC。

3.2 分区补数

分区补数,是针对 Hive、ClickHouse 这类分区表设计的。你想想看,一张表可能有几百个分区,全量重跑太慢了。我只想修某个坏掉的分区,怎么办?

分区补数就是干这个的。它允许你指定一个或多个分区键值,只重跑这些分区。

{
  "type": "partition",
  "table": "ods_order",
  "partitions": ["dt=2024-01-05", "dt=2024-01-07"]
}

这里只重跑 dt=2024-01-05 和 dt=2024-01-07 两个分区,其他分区不动。

注意:分区补数有一个隐含前提——下游任务必须感知到分区级别的变更。如果下游任务只认「表级更新」,你补了分区它也不会重新消费。我建议在调度系统里加一个「分区级血缘追踪」,这样才能精准触发下游重跑。

3.3 表级补数

表级补数,就是整张表全部重跑。听起来简单粗暴,但确实有它的用武之地。

什么时候需要表级补数?

  • 数据源全量重导,比如从业务库重新拉了一整份数据
  • 表结构变更,比如新增了字段,需要重新计算历史数据
  • 数据质量太差,修都修不过来,干脆全量覆盖

表级补数的配置通常很简单:

{
  "type": "table",
  "table": "dws_order_daily",
  "overwrite": true
}

overwrite 参数很关键。true 表示先删后写,false 表示增量覆盖。我建议默认用 true,否则可能出现重复数据。

核心观点:表级补数是「核武器」,杀伤力大但代价也大。全量重跑一张大表可能耗时数小时,还会影响下游依赖。能用分区补数解决的,就别用表级补数。

3.4 任务级补数

任务级补数,是最灵活的一种。它不关心表,也不关心分区,只关心「任务实例」。

你可以指定一个任务 ID,以及这个任务的历史运行时间点,然后重新执行。比如:

{
  "type": "task",
  "task_id": "etl_order_merge",
  "run_ids": ["run_20240105_030000", "run_20240106_030000"]
}

这种模式特别适合那种「任务逻辑变了,需要重跑历史实例」的场景。我记得有一次,数据清洗规则改了,之前跑过的所有实例都得重来。用任务级补数,直接拉出过去 30 天的运行记录,批量重跑,一天就搞定了。

3.5 四种补数范围对比

补数类型 粒度 适用场景 风险等级
时间范围补数 时间窗口 常规数据修复、周期性重跑 低
分区补数 分区键 分区表局部修复 中
表级补数 整张表 全量重导、结构变更 高
任务级补数 任务实例 逻辑变更、历史重跑 中

3.6 补数范围选择策略

实际项目中,这四种补数范围不是互斥的。我通常建议把它们组合起来,形成一个「补数范围矩阵」。

举个例子:

  • 用户选择「时间范围 + 分区」,表示在某个时间范围内,只重跑指定分区
  • 用户选择「任务级 + 时间范围」,表示重跑某个任务在指定时间内的所有实例

这样做的好处是,补数系统可以覆盖 90% 以上的数据修复场景。剩下的 10%,要么是特殊情况手动处理,要么是系统设计没覆盖到。

避坑指南:我曾经设计过一个补数系统,四种范围都支持,但没做「范围冲突检测」。结果用户同时选了「表级补数」和「分区补数」,系统不知道该听谁的。后来我加了一条规则:范围越精确,优先级越高。分区补数优先级高于表级补数,任务级补数优先级高于时间范围补数。

3.7 补数范围的核心逻辑图

下面这张图展示了四种补数范围的关系和选择流程:

补数范围选择流程 补数请求 选择补数范围类型 时间范围补数 biz_date_from/to 分区补数 指定分区键值 表级补数 整表全量重跑 任务级补数 指定任务实例 范围冲突检测 & 优先级裁决 生成补数任务 说明:四种补数范围可组合使用,系统按「精确优先」原则裁决冲突 例如:分区补数优先级 > 表级补数,任务级补数优先级 > 时间范围补数

嗯,这张图基本把补数范围的选择逻辑讲清楚了。从补数请求开始,先选类型,再经过冲突检测和优先级裁决,最后生成补数任务。实际项目中,我还会加一个「补数范围预览」步骤,让用户在执行前能看到哪些分区、哪些实例会被重跑,避免误操作。