3. 监控体系设计:监控分层架构、埋点策略、指标采集方式

数据新鲜度监控,说白了就是给数据管道装一套“仪表盘”。

你想想看,一条数据从业务库产生,经过采集、传输、计算,最终落到数仓或数据湖。这中间任何一个环节卡住,新鲜度就崩了。没有监控,你连崩在哪都不知道。

我刚开始做数据治理时,就吃过这个亏。有一次离线任务延迟了6小时,业务方投诉到老板那,我才发现监控只覆盖了“表是否更新”,根本没管“更新是否及时”。嗯,从那以后,我重新设计了整套监控体系。

3.1 监控分层架构:从底到顶,层层递进

我个人习惯把监控分成三层:基础设施层、任务链路层、数据质量层。每一层关注的点不一样,告警的优先级也不一样。

核心原则:下层告警要收敛,上层告警要精准。别让基础设施的抖动直接触发数据质量告警,否则运维和数仓团队会互相甩锅。

数据新鲜度监控分层架构 数据质量层 关注:表级新鲜度、字段级延迟、跨系统一致性 指标:数据就绪时间、最大延迟时长、延迟分布 告警:业务SLA违约、连续N个周期延迟 任务链路层 关注:ETL任务执行时长、调度依赖、数据流转耗时 指标:任务完成时间、上游产出延迟、排队等待时长 告警:任务超时、依赖断裂、重试次数超阈值 基础设施层 关注:集群资源、网络带宽、存储IO、连接池状态 指标:CPU/内存使用率、磁盘吞吐、网络延迟 告警:节点宕机、磁盘写满、连接数耗尽 告警收敛方向:从下往上,逐层聚合

这三层的关系是这样的:

  • 基础设施层是底座。集群挂了,任务肯定跑不起来。但别因为一台机器重启就疯狂告警,我一般设置5分钟持续异常才触发。
  • 任务链路层是核心。数据延迟90%的原因出在这里:上游产出晚了、任务排队了、SQL跑慢了。
  • 数据质量层是最终体现。业务方只关心“我早上9点看到的报表是不是最新的”,他们不关心你用了什么调度引擎。

我的经验:很多团队只建了第三层,结果延迟了只能看到“表没更新”,但不知道是哪个任务卡住了。一定要把链路层的监控做细,才能快速定位根因。

3.2 埋点策略:在哪埋、埋什么、怎么埋

埋点不是越多越好。埋多了浪费存储,埋少了查不出问题。我总结了一套“三点式”埋点法。

3.2.1 埋点位置:三个关键节点

埋点位置 埋点时机 采集内容 典型场景
数据入口 数据进入管道时 业务时间、到达时间、数据量、来源标识 CDC采集、API接入、文件导入
关键算子 每个ETL步骤完成时 算子开始/结束时间、输入/输出行数、异常记录数 Join、Agg、窗口计算、数据清洗
数据出口 数据写入目标表时 写入时间、写入行数、分区信息、校验结果 Hive表、Kafka Topic、ClickHouse表

为什么要选这三个点?

  • 入口告诉你数据什么时候来的。如果入口时间晚于预期,说明上游系统有问题。
  • 算子告诉你数据在哪一步慢了。我曾经遇到一个场景,数据在入口和出口都正常,但中间有个Join算子因为数据倾斜跑了2小时——没有算子埋点根本发现不了。
  • 出口告诉你数据什么时候可用的。这是业务SLA的最终依据。

3.2.2 埋点内容:最少必要字段

每个埋点事件,我建议只带这6个字段:

{
  "event_id": "uuid",           // 事件唯一ID,用于链路追踪
  "pipeline_name": "order_dw",  // 管道名称
  "node_name": "ods_order",     // 节点名称
  "event_type": "end",          // 事件类型:start/end/error
  "event_time": 1695000000000,  // 事件发生时间(毫秒时间戳)
  "biz_time": 1694995200000,    // 业务时间(数据产生时间)
  "extra": {                    // 扩展字段,按需添加
    "row_count": 1024000,
    "partition": "dt=20230918"
  }
}

注意:别把业务时间(biz_time)和事件时间(event_time)搞混。我见过有人只埋了event_time,结果数据延迟了但看不出来——因为event_time永远是当前时间,根本反映不了新鲜度。

3.2.3 埋点方式:侵入式 vs 非侵入式

对比维度 侵入式埋点 非侵入式埋点
实现方式 在代码中显式调用SDK 通过AOP、拦截器、日志采集
优点 灵活、可携带上下文 无代码侵入、易于统一升级
缺点 耦合业务代码、升级成本高 上下文信息有限、调试困难
适用场景 核心链路、需要精确追踪 通用组件、边缘链路

我个人习惯混合使用:核心链路(比如订单、支付)用侵入式,保证精度;非核心链路(比如日志清洗、临时查询)用非侵入式,降低维护成本。

3.3 指标采集方式:推还是拉?这是个问题

指标采集主要有两种模式:Push(推送)和Pull(拉取)。没有的好坏,看场景选。

3.3.1 Push模式:适合事件型指标

埋点数据主动推送到采集服务。典型实现是Kafka + Flume。

// 伪代码:Push模式埋点
public void onTaskEnd(TaskContext ctx) {
    MetricEvent event = new MetricEvent();
    event.setPipelineName(ctx.getPipelineName());
    event.setNodeName(ctx.getNodeName());
    event.setEventType("end");
    event.setEventTime(System.currentTimeMillis());
    event.setBizTime(ctx.getBizTime());
    // 推送到Kafka
    kafkaProducer.send("metric_topic", event.toJson());
}

优点:实时性好,数据一到就能发出去。适合高频、低延迟的场景。

缺点:如果采集服务挂了,数据可能丢失。需要做好本地缓存和重试机制。

3.3.2 Pull模式:适合状态型指标

采集服务定期去目标系统拉取指标。典型实现是Prometheus + Exporter。

# 伪配置:Prometheus拉取任务指标
scrape_configs:
  - job_name: 'data_pipeline'
    scrape_interval: 15s
    static_configs:
      - targets: ['pipeline-metrics:8080']
    metrics_path: '/metrics'
    params:
      pipeline: ['order_dw', 'user_dw']

优点:采集端可控,不会因为目标系统压力大而丢失数据。适合低频、稳定的指标。

缺点:实时性不如Push,有采集周期延迟。如果目标系统太多,采集端会成为瓶颈。

3.3.3 我的选择策略

指标类型 推荐模式 原因
任务开始/结束时间 Push 需要毫秒级实时性,事件驱动
集群资源使用率 Pull 15秒采集一次足够,状态型指标
数据延迟时长 Push + Pull 实时告警用Push,历史分析用Pull
数据量统计 Pull 分钟级采集即可,避免频繁写入

避坑指南:我曾经在一个项目里全部用Push模式,结果业务高峰期Kafka集群被打爆,丢了一堆指标。后来改成核心指标Push、非核心指标Pull,才稳定下来。记住:Push模式一定要做背压控制和降级策略。

3.4 小结:监控体系设计的三个要点

聊了这么多,其实就三句话:

  1. 分层要清晰。基础设施、任务链路、数据质量,各管各的,别混在一起告警。
  2. 埋点要精准。入口、算子、出口三个点埋好,6个字段带齐,别贪多。
  3. 采集要灵活。Push和Pull混着用,核心指标保实时,非核心指标保稳定。