外观
数据新鲜度 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=yesterday7. 与实时 Lag 的统一展示
同一业务主题建议在一张「新鲜度大盘」同时展示:
| 对象类型 | 主指标 | SLA 示例 |
|---|---|---|
| 离线分区表 | ready_ts vs deadline | 09:30 前就绪 |
| Kafka 消费组 | Lag(消息数/时间) | Lag < 10 万或 < 5 分钟 |
| Flink 作业 | Watermark 延迟 | 事件延迟 p99 < 3 分钟 |
避免运营只看离线绿灯、却不知实时已停表。跨域链接:Kafka 积压 / Lag、实时链路排查。
常见坑(至少牢记这些)
任务成功即就绪
空分区、伪成功最坑业务。就绪必须含数据断言。SLA 写「尽量 9 点」无法度量
必须是时刻 + 时区 + 对象表。只监控最末 ADS
上游 DWD 延迟时,ADS 九死一生。关键路径分层监控。补数把 ready_ts 刷新成「刚完成」却不标注
历史 SLA 报表被污染;补数要打标。实时用消费墙钟冒充事件新鲜度
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 原创数仓/面试文,已改写成可执行清单;未包含未公开公司数据与内部表名。