Skip to content

数据新鲜度 SLA 监控 ​

难度与前置

难度:入门
前置:有离线分区表或实时 Topic;知道「任务成功」≠「数据可用」。
读完能做什么:为表/Topic 定义新鲜度 SLA,落地水位与告警,区分「调度失败」与「空分区假成功」,并用清单验收。

适用场景 ​

  • 业务问「今天日报几点能看」,需要可承诺、可度量的时间
  • 任务绿勾但分区为空/延迟,下游已错误开算
  • 实时链路 Lag 与离线分区就绪要统一口径展示

不适用:

  • 无稳定业务日/分区契约的临时表
  • 一次性导数据(不必上 SLA 平台)
  • 尚未理清依赖(先做 调度依赖)

真实场景(一条) ​

运营约定「每天 09:30 前 ads_ad_daily_report_1d 可用」。某日调度显示成功,但上游渠道文件晚到,DWD 空分区,ADS 用旧逻辑写出 0 行仍成功。业务 09:10 打开看板是空的,投诉 SLA 失守。

改造:新鲜度 = 分区存在 ∧ 行数≥下限 ∧ 最大事件时间达标 ∧ 质量门禁通过;09:00 预警、09:30 违约;空分区当失败。事故率下降,值班按清单处理。

怎么做(步骤清单) ​

1. 定义新鲜度(不要只定义「任务结束时间」) ​

对每张对外表约定:

字段示例
对象ads_ad_daily_report_1d
业务日dt
就绪条件分区可见 + row_cnt >= L + 质量规则 PASS
SLA 时刻业务日 +1 的 09:30(Asia/Shanghai)
预警时刻09:00
Owner / 值班投放数仓 oncall

实时对象可定义为:watermark 或 max(event_ts) 落后墙钟 < X 分钟,且 Lag < Y。

2. 采集水位信号 ​

离线常见信号:

sql
-- 分区就绪元数据表(由调度/质量任务写入)
CREATE TABLE IF NOT EXISTS meta_partition_freshness (
  table_name   STRING,
  dt           STRING,
  ready_ts     TIMESTAMP COMMENT '满足就绪条件的时间',
  row_cnt      BIGINT,
  max_event_ts TIMESTAMP,
  dq_status    STRING,
  job_id       STRING
)
PARTITIONED BY (biz_date STRING);
sql
-- 每次分区完成后 UPSERT
INSERT INTO meta_partition_freshness PARTITION (biz_date = '${biz_date}')
SELECT
  'dwd_ad_spend_detail_di' AS table_name,
  '${biz_date}' AS dt,
  CURRENT_TIMESTAMP() AS ready_ts,
  COUNT(*) AS row_cnt,
  MAX(event_ts) AS max_event_ts,
  'PASS' AS dq_status,
  '${job_id}' AS job_id
FROM dwd_ad_spend_detail_di
WHERE dt = '${biz_date}'
HAVING COUNT(*) >= ${min_rows};

实时:Kafka Lag、Flink currentInputWatermark、下游表 max(etl_ts)。

3. 计算延迟与违约 ​

sql
-- 日终:是否在 SLA 前就绪
SELECT
  table_name,
  dt,
  ready_ts,
  -- sla_deadline 示例:dt 次日 09:30 上海时区,按引擎时区函数改写
  CASE WHEN ready_ts <= sla_deadline_ts THEN 'OK' ELSE 'BREACH' END AS sla_status,
  unix_timestamp(ready_ts) - unix_timestamp(sla_deadline_ts) AS delay_sec
FROM meta_partition_freshness f
JOIN dim_table_sla s ON f.table_name = s.table_name
WHERE f.biz_date = '${biz_date}';

4. 告警分级 ​

级别条件动作
通知过预警时刻未就绪值班群 @owner
严重过 SLA 未就绪电话/升级;冻结下游可选
空分区成功但行数 < L直接严重,禁止当「绿」

告警内容必须带:table、dt、已延迟多久、上游依赖状态、runbook 链接。

5. 与调度、质量联动 ​

  • 调度成功钩子 ≠ 写 freshness;质量通过后才写 ready_ts
  • 下游依赖「数据就绪」而不是「任务成功」(见 调度依赖)
  • 补数重跑需更新 ready_ts 或单独标记 is_backfill

6. 看板与周报 ​

  • 核心表 SLA 达成率(按周)
  • Top 违约表与根因标签(上游晚到 / 资源排队 / SQL 变慢 / 空分区)
  • 实时:Lag 与事件延迟分位
bash
# 示意:导出昨日违约
# SELECT * FROM sla_breach_1d WHERE dt=yesterday

7. 与实时 Lag 的统一展示 ​

同一业务主题建议在一张「新鲜度大盘」同时展示:

对象类型主指标SLA 示例
离线分区表ready_ts vs deadline09:30 前就绪
Kafka 消费组Lag(消息数/时间)Lag < 10 万或 < 5 分钟
Flink 作业Watermark 延迟事件延迟 p99 < 3 分钟

避免运营只看离线绿灯、却不知实时已停表。跨域链接:Kafka 积压 / Lag、实时链路排查。

常见坑(至少牢记这些) ​

  1. 任务成功即就绪
    空分区、伪成功最坑业务。就绪必须含数据断言。

  2. SLA 写「尽量 9 点」无法度量
    必须是时刻 + 时区 + 对象表。

  3. 只监控最末 ADS
    上游 DWD 延迟时,ADS 九死一生。关键路径分层监控。

  4. 补数把 ready_ts 刷新成「刚完成」却不标注
    历史 SLA 报表被污染;补数要打标。

  5. 实时用消费墙钟冒充事件新鲜度
    Lag=0 仍可能事件时间停住(空闲分区 / 源停写)。

如何验收(可量化) ​

  • [ ] 对外表均有 SLA 时刻、就绪谓词、owner
  • [ ] meta_partition_freshness(或等价)日更且可查
  • [ ] 人为制造空分区:告警为严重且下游不启动
  • [ ] 连续两周达成率可出报表;违约有根因
  • [ ] 业务方拿到的「可用时间」与系统 ready_ts 一致
sql
-- 验收:昨日核心表违约列表应为空或已认领
SELECT table_name, dt, delay_sec, root_cause
FROM ads_sla_breach_1d
WHERE dt = date_sub(current_date(), 1)
  AND tier = 'P0'
  AND ticket_status IS NULL;
sql
-- 验收:就绪谓词含行数
SELECT table_name, dt, row_cnt
FROM meta_partition_freshness
WHERE biz_date = '${biz_date}' AND row_cnt < min_rows_threshold;

相关面试题 ​

占位:与题库小程序对齐后补链接(建议关联:数据新鲜度、SLA、分区就绪、调度依赖与质量门禁)。


改写说明:结构与判断标准参考 Wood 原创数仓/面试文,已改写成可执行清单;未包含未公开公司数据与内部表名。