订阅更新

数仓中的迟到数据怎么处理?

面试问 038 约 3 分钟读完 3 次阅读

本文目录
  1. 面试怎么回答
  2. 第一步:先区分事件时间和到达时间
  3. 第二步:明确可接受的迟到边界
  4. 第三步:按事件日期定向修正
  5. 第四步:保证补写和重跑幂等
  6. 一个典型场景

面试怎么回答

我会先区分事件时间和到达时间,再按业务 SLA 定义窗口内迟到、窗口外可修正和超期异常。对可修正数据,根据事件时间定位受影响分区,以业务主键幂等回写,并沿血缘定向重算下游汇总。最后校验主键、行数和核心指标,记录修正批次,确保补数可追踪、可重试,不会因为重复到达再次算错。

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

详细讲解

很多人第一反应是:

“把昨天的任务重跑一遍。”

重跑确实是一种补救手段,但它没有回答三个关键问题:数据到底迟到了多久、应该改写哪个业务日期、重复到达时会不会再次把指标算错。

迟到数据真正考验的不是调度系统会不会补跑,而是:

能不能把事件发生时间、数据到达时间和最终修正机制设计成一个可追踪的闭环。


第一步:先区分事件时间和到达时间

假设一笔订单 8 月 20 日完成,但上游接口到 8 月 22 日才把记录传过来:

  • 事件时间是 8 月 20 日
  • 到达时间是 8 月 22 日
  • 处理时间可能是 8 月 22 日任务运行时

如果报表统计“8 月 20 日成交额”,这笔订单应该回到 8 月 20 日,而不是被算进 8 月 22 日。

所以设计表时,至少要保留业务事件时间和数据进入系统的时间。只保留分区日期,后面很难判断数据属于哪一天、迟到了多久。


第二步:明确可接受的迟到边界

不是所有数据都要无限期等待。

通常可以按业务 SLA 分三层:

窗口内迟到

例如 T+1 报表允许等待到次日 10 点。窗口关闭前到达的数据直接参与正常计算。

窗口外可修正

数据超过 SLA 才到,但仍在业务允许的回溯周期内。系统记录受影响的事件日期,并触发定向补算。

超期异常

超过最大回溯周期的数据不再静默改历史,而是进入异常队列,由数据和业务负责人确认是否修正。

边界越清楚,实时性、准确性和补算成本之间的取舍才越可控。


第三步:按事件日期定向修正

事件时间与到达时间修正链路

迟到数据在 8 月 22 日到达,不代表只重跑 8 月 22 日分区。

正确的修正流程通常是:

  1. 根据事件时间识别受影响的业务日期;
  2. 记录待修正分区和影响范围;
  3. 对目标明细表执行幂等写入;
  4. 从明细层向汇总层定向重算;
  5. 校验主键、行数和核心指标差异。

如果下游有日、周、月多级汇总,还要沿血缘找到所有受影响的结果,而不是只补最上游一张表。


第四步:保证补写和重跑幂等

迟到数据可能不只来一次,补数任务也可能失败重试。

常见做法包括:

  • 以业务主键做 MERGE 或覆盖更新
  • 重算目标分区,而不是在旧结果上继续累加
  • 保存修正批次、到达时间和处理状态
  • 补算前后对主键重复、金额和记录数做核对

如果补数逻辑不是幂等的,同一批数据重跑两次,迟到问题就会变成重复问题。


一个典型场景

比如移动端埋点偶尔离线两天,恢复网络后才批量上报。

最初系统只按当天处理分区增量计算,8 月 20 日的事件在 8 月 22 日到达后,被写进 8 月 22 日统计,导致两天的活跃和转化都不准确。

只重跑 8 月 22 日无法修复 8 月 20 日。正确做法是保留事件日期,识别受影响分区,幂等回写 8 月 20 日明细,再定向刷新对应日、周汇总,并记录这次修正。

迟到数据不是“晚跑一次任务”,而是一次历史口径修正。


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