CalcGuide · 技术博客主页 / 一页纸学习计划
🟠

数据治理、质量与血缘:从 dbt 测试到 OpenLineage

分类:数据与人工智能 · 路径:docs/topics/data-quality-and-lineage/README.md

#data-quality#lineage#dbt#great-expectations#openlineage

用 dbt tests + Great Expectations + OpenLineage 把数据治理和质量门禁变成流水线一环

父主题

数据工程基础:从 ETL 到数仓与流处理

子主题(0)

数据治理、质量与血缘:从 dbt 测试到 OpenLineage

0. 元信息

1. 学习路线

数据契约 → dbt 转换与测试 → Great Expectations 期望 → Soda 分布异常 → OpenLineage 血缘 → Marquez / DataHub 目录 → 可观测

2. 阶段周数分配

阶段2 周方案2.5 周方案备注
1. 数据契约1 天1.5 天schema + owner + SLA + version
2. dbt 转换1.5 天2 天staging / intermediate / marts
3. dbt 测试1.5 天2 天5 类测试 + 失败告警
4. Great Expectations1.5 天2 天Expectation + Checkpoint
5. Soda1 天1.5 天SodaCL + 扫描 + 告警
6. OpenLineage1.5 天2 天Run / Job / Dataset / Facet
7. 数据目录1 天1.5 天Marquez / DataHub
8. 治理落地0.5 天1 天SLA + On-call + 复盘

每天 1.5~2 小时。2 周方案专注前 5 阶段;2.5 周方案多 2 天做血缘与治理落地。

3. 核心知识 / 产出 / 标准表

阶段核心知识实践产出可观察学会标准
1. 数据契约Schema、Owner、SLA、版本化、Schema Registry一份数据契约 YAML/Protobuf能讲清契约四要素
2. dbt 转换sources / staging / intermediate / marts、incremental、materialization一份 dbt 项目(5 模型)能跑通 dbt build
3. dbt 测试unique / not_null / accepted_values / relationships / freshness5 类测试 + 失败告警能解释 5 类测试与失败处置
4. Great ExpectationsExpectation、Checkpoint、Data Docs10 条 Expectations + Data Docs 站点能写出 5 种分布异常检测
5. SodaSodaCL、Soda Core、扫描 + 失败告警一份 Soda 检查 YAML能区分语法/语义/分布异常
6. OpenLineageRun / Job / Dataset / Facet、Marquez一份 OpenLineage 事件流 + Marquez UI能用 SQL 查血缘
7. 数据目录DataHub / Unity Catalog、标签、Glossary一份带标签的目录能查表/列/指标
8. 治理落地SLA、On-call、事故复盘一份事故复盘 + 改进行动能把质量问题接到 on-call

4. 第一周(每天 1.5~2 小时)

Day 1 约定:本计划使用 Docker Compose 起 PostgreSQL + dbt + Great Expectations + Marquez。dbt 跑 dbt build / dbt test;GE 跑 great_expectations checkpoint run;血缘事件用 openlineage-client 发到 Marquez HTTP endpoint。所有契约存为 YAML / Protobuf,版本化在 Git。

任务当天交付自检
Day 1装 Docker Compose + PostgreSQL + dbt-postgres + Great Expectations;用 dbt init 建一个 dbt 项目;写 sources.yml 指向 PostgreSQL raw.ordersdbt 项目骨架 + sources.ymldbt debug 通过;dbt run --select source:raw.orders 成功;SHOW SOURCESraw.orders
Day 2数据契约:写一份 contracts/orders.yaml(schema + owner + SLA + version 4 要素);用 Protobuf 翻译成 orders.proto;两份文件同时进 Git契约 YAML + ProtobufYAML 4 要素齐;protoc --decode 输出与 YAML 一致;Git 提交记录显示版本号递增
Day 3dbt 转换:写 3 层 dbt models(stg_orders / int_orders_cleaned / fct_orders_daily);dbt_project.yml 配 staging 视图、intermediate 增量、marts 物化表3 层 dbt models + dbt_project.ymldbt run 全部 success;dbt show --select fct_orders_daily 输出行数与源表一致;3 层命名规范符合 staging/intermediate/marts
Day 4dbt 测试:在 schema.yml 加 5 类测试(unique / not_null / accepted_values / relationships / freshness);故意制造 unique 冲突看测试失败;配 on-run-end 失败告警5 类测试 + 失败日志dbt test 输出 5 passed;故意冲突后 dbt test 失败并打印 fail 详情;dbt build 失败时 exit code 非 0
Day 5Great Expectations:用 great_expectations init 建 GE 项目;写 5 条 Expectations(ExpectColumnValuesToNotBeNull / ExpectColumnValuesToBeUnique / ExpectColumnValuesToBeBetween / ExpectColumnMeanToBeBetween / ExpectColumnStdevToBeBetween);配 Checkpoint5 条 Expectations + Checkpointgreat_expectations checkpoint run orders_checkpoint 输出 5 passed;Data Docs 站点可访问;ExpectColumnMeanToBeBetween 检测分布异常
Day 6OpenLineage + Marquez:起 Marquez(docker compose up marquez);用 openlineage-client Python SDK 手动发一份 Run Start / Complete 事件;在 Marquez UI 查 Job → Dataset 血缘OpenLineage 事件脚本 + Marquez 截图Marquez UI 显示 Job 与 Dataset 节点;Run 事件含 run.facets.errorMessagenominalTime;用 marquez-cli lineage get <dataset> 查 SQL 血缘
Day 7步骤 A:跑通 dbt + GE + OpenLineage 最小治理链路(dbt build → GE checkpoint → 发 OpenLineage 事件到 Marquez);步骤 B:补齐 4 类边界(契约漂移、测试失败阻塞、血缘事件丢失、SLA miss 不告警)治理链路 + 故障演练报告pytest -k test_data_governance 4 个用例全过;每类故障复现 + 防护措施写到 notes/week1-day7.md

Day 7 执行次序

步骤 A —— 最小可用治理链路(60~90 分钟)

  1. dbt build 跑通(run + test);
  2. GE checkpoint 跑通(5 passed);
  3. 写 Python 脚本发 OpenLineage 事件到 Marquez;
  4. Marquez UI 看到血缘;
  5. 故意改源 schema 制造契约漂移,看告警。

步骤 B —— 4 类边界用例(30~45 分钟)

#用例期望行为验证命令
B1契约漂移(源 schema 加列)dbt 测试失败 + 告警pytest -k test_contract_drift
B2dbt 测试失败阻塞下游 + Slack 告警pytest -k test_dbt_test_fail
B3OpenLineage 事件丢失补发 + DLQ 告警pytest -k test_ol_event_lost
B4SLA miss 不告警配 SLA checker + 强制告警pytest -k test_sla_alert

Day 7 当天必完成步骤 A;步骤 B 至少完成 B1、B2。

5. 阶段通用验收

  1. 不看答案独立重写 dbt 3 层 + 5 类测试 + GE Checkpoint + OpenLineage 事件流;
  2. 用自己的话解释”为什么需要数据契约""为什么测试要阻塞下游""为什么血缘要列级而非仅表级”;
  3. 画一张图:契约 + 转换 + 测试 + 血缘全链路图(三件套之一);
  4. 测试契约漂移、测试失败、分布异常、血缘事件丢失、SLA miss 5 类边界;
  5. 准备至少 3 组自定义数据集并贴出实际测试结果与血缘截图;
  6. 记录 dbt build 时长、测试通过率、GE Checkpoint 失败率、OpenLineage 事件成功率 4 个核心指标;
  7. 能修改已有契约(加列 / 改 SLA)并验证血缘自动更新。

交付存放:第 3 项的图、第 5 项的输出、第 6 项的指标,统一存到 week1/notes/week1/<dataset>/README.md

6. 最终验收

7. 综合项目

首选:端到端数据治理(必做:数据契约 + dbt + GE + OpenLineage + Marquez + Slack 告警)。
备选:分布异常监测(Soda + 历史基线 + 自动告警)。
备选:数据目录 + 治理门户(DataHub + dbt 集成 + 标签 + Glossary + 影响分析)。

端到端治理必做要求:

任何综合项目都必须包含:

  1. 需求说明与数据契约(4 要素齐:schema + owner + SLA + version);
  2. 全链路架构图与命名规范;
  3. 核心代码(dbt models + GE Checkpoint + OpenLineage 事件 + Slack 告警 callback);
  4. 边界测试(契约漂移、测试失败、分布异常、血缘事件丢失、SLA miss);
  5. 可观测(GE Data Docs + Marquez UI + Slack 告警日志 + Grafana metrics);
  6. README(设计取舍、测试选型理由、下一步);
  7. 复盘记录(模拟 1 次 P0 故障,写 retrospective.md);
  8. notes/ 规范
文件内容
notes/design.md全链路架构图 + 契约四要素表 + 命名规范
notes/test.md每组测试的输入 / 期望 / 实际 / 通过情况
notes/retrospective.md用时、难点、收获、改进点
notes/runbook.md常见失败 + 处置 SOP(契约漂移 / 测试失败 / 血缘缺失 / SLA miss)
notes/marquez-screenshots/Marquez UI 截图(Job / Dataset / Column Lineage)
notes/dbt-test-reports/dbt test 输出 + 失败详情
notes/contract-yaml/数据契约(YAML + Protobuf 双份)
notes/sample-data/至少 3 组测试数据集 + 测试结果对比表

本主题贡献

数据治理的核心矛盾是”数据团队生产量大 vs 业务方不敢信”。本子主题专门讲清 Great Expectations + OpenLineage + Marquez 如何把这条信任墙拆掉——以 Great Expectations 为”期望即代码”的事实标准,OpenLineage 为血缘事件开放规范,Marquez 为血缘目录事实实现,SLA 为治理硬指标;不重复父主题的 dbt 基础与 Iceberg 存储。

3 职责

  1. 用 Great Expectations Checkpoint 把 10 条 Expectations(ExpectColumnValuesToNotBeNull / ExpectColumnValuesToBeUnique / ExpectColumnValuesToBeBetween / ExpectColumnMeanToBeBetween / ExpectColumnStdevToBeBetween)做成可阻塞的质量门禁,失败阻塞下游 dbt run / Airflow Task。
  2. 用 OpenLineage 事件(Run Start / Complete / Fail,含 run.facets.errorMessage / nominalTime / dataset.facets.schema)把每个 Task 的输入输出数据集上报到 Marquez,血缘由”人维护”变成”自动产生”。
  3. 用 SLA 三件套(freshness / completeness / validity)为关键数据集定硬指标——dbt source freshness + GE ExpectColumnValuesToNotBeNull + Marquez nominalTime 监控,SLA miss 接 Slack / PagerDuty 告警。

4 交付物

  1. 一份 Great Expectations 项目(10 条 Expectations + Checkpoint + Data Docs 站点),含 5 种分布异常检测(均值 / 标准差 / 分位数 / 唯一值比例 / NULL 比例),Checkpoint 失败 exit code 非 0。
  2. 一份 OpenLineage 事件脚本(Python openlineage-client SDK + dbt-ol 集成 + Airflow OpenLineage provider),每个 Task 自动发 Run Start / Complete,含 Job / Dataset / Run Facet。
  3. 一份 Marquez 部署(docker compose up marquez)+ 血缘查询示例(marquez-cli lineage get <dataset>),含 Job → Dataset 血缘截图 + 列级血缘验证。
  4. 一份 SLA 监控配置(dbt source freshness + GE Checkpoint + Marquez nominalTime 监控),含 Slack / PagerDuty 告警 callback,SLA 文档写明 4 要素:freshness / completeness / validity / owner。

3 指标

  1. Great Expectations Checkpoint 通过率 ≥ 99%(失败 Checkpoint 阻塞下游,强制修复后重跑)。
  2. OpenLineage 事件成功率 ≥ 99.5%(Task 完成时事件必达 Marquez,缺失即告警)。
  3. SLA miss 告警响应 < 5 min(freshness 超时 → Slack 通知 → on-call 介入)。

8. 推荐开源资料

阶段角色资料链接用法
全部主线书Reis & Housley《Fundamentals of Data Engineering》Ch.8~10https://www.oreilly.com/library/view/fundamentals-of-data/9781098108298/治理与可观测必读
1契约Confluent Schema Registryhttps://docs.confluent.io/platform/current/schema-registry/index.html契约存储与兼容性
1契约Protobuf 官方文档https://protobuf.dev/跨语言 Schema
2~3转换dbt 官方文档https://docs.getdbt.com/转换 + 测试 + 文档
4质量Great Expectations 官方文档https://docs.greatexpectations.io/期望即代码
5质量Soda 官方文档https://docs.soda.io/SodaCL + Soda Core
6血缘OpenLineage 规范https://openlineage.io/血缘事件标准
6血缘Marquez 官方文档https://marquezproject.ai/血缘 UI 实现
7目录DataHub 官方文档https://datahubproject.io/元数据目录
7目录Unity Catalog 文档https://docs.unitycatalog.io/Databricks 目录
8可观测Monte Carlo Bloghttps://www.montecarlodata.com/blog/数据可观测理念
8可观测Datafold Bloghttps://www.datafold.com/blog数据测试理念

许可证提示:dbt Core / GE / Soda / OpenLineage / Marquez / DataHub 都是 Apache-2.0;Unity Catalog 是商业版。复制 Apache 项目示例前请保留 LICENSE 与 NOTICE。默认做法是读规范后自己写测试与契约,而不是复制官方 Example。

默认使用顺序:先读 Reis《Fundamentals of Data Engineering》第 8~10 章建立治理心智 → 装 dbt + GE → 写数据契约(YAML + Protobuf)→ 写 dbt 3 层 models → 配 5 类 dbt 测试 → 加 GE Checkpoint + Data Docs → 起 Marquez + OpenLineage → 用 Slack 告警 → 跑端到端治理演练 → 写 notes/retrospective.md

9. 学习资料汇聚(v0.3 自包含)

本节由本计划生成。链接指向原始材料或作者公开内容。规范会演进,记录时务必写明版本与日期。

9.1 背景与动机

数据团队的核心痛点不是”没数据”,而是”数据不可信”。脏数据进仓 → 错报表 → 错决策 → 业务损失。传统做法靠人工抽样检查,扩展性差。dbt 2016 年开源把”转换即代码 + 测试即代码”带入主流;Great Expectations 2018 年、Soda 2020 年先后开源,把”期望/检查即代码”做成事实标准。OpenLineage 2021 年由 Linux Foundation 发起,把血缘(lineage)从厂商特性做成开放标准,与 Marquez / DataHub / Unity Catalog 互操作。今天数据团队的”治理成熟度”由血缘完整度、契约覆盖率、测试通过率三项指标衡量。

9.2 概念地图

flowchart LR
  Src[源系统] --> Contract[数据契约]
  Contract --> Ingest[摄取]
  Ingest --> Lake[Lakehouse]
  Lake --> dbt[dbt 转换]
  dbt --> Test[dbt 测试]
  Lake --> GE[GE 期望]
  dbt --> Soda[Soda 检查]
  Test --> Gate[质量门禁]
  GE --> Gate
  Soda --> Gate
  Gate --> Serve[服务 BI/API/ML]
  dbt --> OL[OpenLineage 事件]
  Ingest --> OL
  Lake --> OL
  OL --> MQ[Marquez]
  OL --> DH[DataHub]
  Serve --> Obs[可观测]

9.3 基础知识讲解

9.3.1 经典论文 / 规范

资料贡献读法
OpenLineage Specification 1.x血缘事件标准必读 Facet 部分
Andrew Ng et al., Data Quality: The Foundation of Modern Data(2022)数据质量概念选读
Barrons et al., Data Contracts: A Unified Standard for Data(2023)数据契约选读

9.3.2 经典书籍

侧重用法
Joe Reis & Matt Housley, Fundamentals of Data Engineering(O’Reilly 2022)数据工程生命周期必读第 8~10 章
Julien Kervizic, Observability for Data Engineering(Leanpub 2024)数据可观测选读
Svetlana Siccama, Data Quality Assessment(2023)数据质量评估选读

9.3.3 优秀博客与文档

资料特点用法
dbt 官方文档转换 + 测试 + 文档必读
Great Expectations 官方文档期望即代码必读 Expectations + Checkpoint
Soda 官方文档SodaCL + Soda Core必读 SodaCL
OpenLineage 官方文档血缘标准必读 Spec
Monte Carlo Blog数据可观测理念选读
Datafold Blog数据测试选读

9.3.4 核心人物

人物影响材料
Drew Banindbt 起源dbt 博客
Tristan Handydbt Labsdbt 博客
James CampbellSoda 起源Soda 博客
Abe GongGreat ExpectationsGE 博客

9.3.5 开发方法

方法动作何时用
Contract-first先写契约,再写代码任何新管道
Test-as-code测试与模型同仓库任何 dbt 项目
Quality gate测试失败阻塞下游上线前必加
Lineage everywhere每个 Task 发 OpenLineage 事件任何生产流水线
SLI/SLO for data衡量 fresh / complete / valid任何关键数据集

9.4 经典问题与经典案例(≥5 道)

#问题重要性最简答案
1数据契约四要素治理基础schema + owner + SLA + 版本
2dbt incremental 怎么写性能is_incremental() + unique_key
3GE 与 Soda 怎么选选型GE 重期望文档、Soda 重扫描
4OpenLineage 怎么接血缘Airflow 用 OpenLineageProvider
5分布异常怎么检测高级质量用历史分布 + 偏差阈值
6血缘表级 vs 列级精细度关键场景用列级(OpenLineage Column Lineage)
7数据测试 CI/CD工程化用 dbt build + GitHub Actions
8SLA miss 怎么告警反馈链路用 SLA checker + Slack
9Schema Registry 怎么选契约存储Confluent SR / Apicurio / 自建
10数据可观测 vs 监控概念监控看指标、可观测看变化原因

9.5 学习难点

概念难点

难点突破路径
契约 vs Schema写四要素对照
测试 vs 检查dbt 测试重静态、Soda 重动态
血缘 vs 影响分析血缘是依赖,影响是变更爆炸半径

思维难点

难点突破路径
阈值怎么设用历史分布 + 业务 SLA
血缘覆盖率看”关键数据集是否有 owner + SLA”

工程难点

难点突破路径
dbt 项目膨胀用 staging / intermediate / marts 三层
GE 大检查超时用 Checkpoint 拆分
OpenLineage 事件丢失加 retry + DLQ

9.6 技术标准与接口

Entity

名称版本组织状态许可证
dbt Core / Cloud1.x / 最新dbt Labs活跃Apache-2.0 / 商业
Great Expectations0.18+GE活跃Apache-2.0
Soda Core3.xSoda Data活跃Apache-2.0
OpenLineage1.xOpenLineage活跃Apache-2.0
Marquez1.xOpenLineage活跃Apache-2.0
DataHub0.xLinkedIn / DataHub活跃Apache-2.0
Unity CatalogDatabricks商业商业
Apache Atlas2.xApacheGAApache-2.0

Scope

dbt 是转换 + 测试;GE / Soda 是质量检查;OpenLineage 是血缘标准;Marquez / DataHub / Atlas 是目录实现。它们互补,不替代。

Structure

Ecosystem

Depth Tiers

层级能力标准
L0知道存在知道 dbt/GE/Soda/OpenLineage 各自定位
L1看得懂示例能读懂 dbt model + schema.yml
L2能正确调用能用 dbt build + GE Checkpoint
L3能解释与排错能定位血缘缺失、契约漂移、测试失败
L4能设计与扩展能设计整套数据治理框架

本子主题目标:L3

Source

9.7 关键代码

9.7.1 dbt model + schema.yml(5 类测试)

# 9.7.1 dbt project/models/staging/schema.yml
version: 2

models:
  - name: stg_orders
    columns:
      - name: order_id
        tests:
          - unique
          - not_null
      - name: user_id
        tests:
          - not_null
          - relationships:
              to: ref('stg_users')
              field: user_id
      - name: status
        tests:
          - accepted_values:
              values: ['pending', 'paid', 'shipped', 'cancelled']
      - name: order_date
        tests:
          - not_null
      - name: amount
        tests:
          - not_null
    config:
      contract:
        enforced: true
-- 9.7.1.2 dbt incremental model
{{ config(materialized='incremental', unique_key='order_id') }}

SELECT
    order_id,
    user_id,
    amount,
    order_date,
    status
FROM {{ source('raw', 'orders') }}

{% if is_incremental() %}
WHERE order_date > (SELECT MAX(order_date) FROM {{ this }})
{% endif %}

9.7.2 Great Expectations Checkpoint

# 9.7.2 Great Expectations 配置 + Checkpoint
import great_expectations as gx

context = gx.get_context(mode="file", project_root_dir="./gx")

batch = context.get_batch(
    batch_definition=context.data.add_pandas_filesystem(
        name="orders", base_directory="./data"
    ),
    batch_parameters={"path": "./data/orders.parquet"},
)

suite = context.suites.add(
    gx.ExpectationSuite(name="orders_suite")
)
suite.add_expectation(gx.expectations.ExpectColumnValuesToNotBeNull(column="order_id"))
suite.add_expectation(gx.expectations.ExpectColumnValuesToBeUnique(column="order_id"))
suite.add_expectation(gx.expectations.ExpectColumnValuesToBeBetween(
    column="amount", min_value=0, max_value=1_000_000
))
suite.add_expectation(gx.expectations.ExpectColumnMeanToBeBetween(
    column="amount", min_value=10, max_value=10_000
))

checkpoint = context.checkpoints.add(
    gx.Checkpoint(name="orders_checkpoint", suites=[suite], actions=[
        gx.checkpoint.UpdateDataDocsAction(name="docs"),
    ])
)
checkpoint.run(batch=batch)

9.7.3 OpenLineage + Airflow

# 9.7.3 Airflow + OpenLineage Provider 配置
from airflow import DAG
from airflow.providers.openlineage.sensors.openlineage import OpenLineageSensor
from airflow.operators.bash import BashOperator

dag = DAG("orders_etl", openlineage_integration=True)

extract = BashOperator(
    task_id="extract",
    bash_command="echo extract",
    dag=dag,
    inlets=[{"type": "database", "name": "raw.orders"}],
    outlets=[{"type": "table", "name": "dw.ods_orders"}],
)

10. 常见误区

11. 所有知识点分类

  1. 编程语言
  2. 数据结构与算法
  3. 计算机基础
  4. 工程技术
  5. Web 与后端
  6. 前端与客户端
  7. 数据与人工智能
  8. 项目与职业能力
  9. 安全与可靠性

本计划归属:数据与人工智能 主 + 工程技术 辅。


直接依赖(2)

查看知识图谱