OpenLineage 是什么?跨 Spark、Flink、Airflow 的血缘怎么统一采集?

第 1268 题 约 3 分钟读完

技术点:数据治理

本文目录
  1. 面试怎么回答
  2. 传统血缘采集的问题
  3. OpenLineage 的模型
  4. 各引擎怎么接入
  5. 落地时要注意

面试怎么回答

传统血缘靠解析 SQL,Spark 代码和 Python 脚本覆盖不到,每个引擎还要单独开发 Hook,而且只有静态关系,没有每次运行的信息。OpenLineage 是一个开放的血缘标准,模型是 Job、Run、Dataset 三个对象,作业运行时发出 START、COMPLETE、FAIL 等 RunEvent,带上输入输出数据集,再通过 Facet 扩展 Schema、列级血缘、行数、SQL 等信息。Spark 加一个 Listener 从执行计划里提取,SQL 和 DataFrame 都能覆盖;Airflow 有官方 Provider,还能把 Task 和它触发的 Spark 作业关联起来;Flink、dbt 也有集成。事件通过 HTTP 或 Kafka 发到 Marquez、DataHub 这类后端。落地关键是各引擎的数据集命名要统一,否则连不上;要统计覆盖率,上报异步不能影响作业,再和 SQL 静态解析互补。

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

详细讲解

很多公司的血缘系统只能解析 Hive SQL,Spark 代码作业、Flink 作业、Python 脚本的血缘都是断的。OpenLineage 是 LF AI & Data 基金会下的开放血缘标准,想解决的就是「各个引擎都按同一种格式上报血缘」。面试官问这题,想看你做血缘时有没有想过解析之外的采集方式。

传统血缘采集的问题

  • 靠解析 SQL:只能覆盖 SQL 作业,Spark DataFrame 代码、Python 脚本、临时表、动态 SQL 都解析不全;
  • 每个引擎单独适配:Hive 用 Hook,Spark 写 Listener,Flink 又是另一套,每个都要自己开发和维护;
  • 只有静态关系:知道表 A 产生表 B,但不知道某一次运行读了哪个分区、写了多少行、成功还是失败。

OpenLineage 的模型

OpenLineage 定义了一种标准的事件格式,核心是三个对象:

  • Job:一个作业(比如一个 Airflow Task、一个 Spark 应用);
  • Run:作业的一次运行,有唯一的 runId;
  • Dataset:作业读写的数据集,分成 inputs 和 outputs。

作业在运行过程中发出 RunEvent,事件类型包括 START、RUNNING、COMPLETE、FAIL、ABORT。每个对象都可以挂 Facet(扩展信息),比如 Schema、列级血缘、数据量、SQL 文本、数据质量结果、父作业关系等。

各引擎怎么接入

  • Spark:加一个 OpenLineage 的 SparkListener(配 spark.extraListeners),它从执行计划里提取输入输出,不管是 SQL 还是 DataFrame 代码都能拿到,还支持列级血缘;
  • Flink:通过 Flink 的 JobListener / 新的血缘接口上报 Source 和 Sink;
  • Airflow:官方的 OpenLineage Provider,自动从 Operator 里提取血缘,并把 Task 和它触发的 Spark 作业通过父 Run 关联起来;
  • dbt:有专门的集成,从 dbt 的元数据里生成事件。

事件发到哪里由 Transport 决定(HTTP、Kafka、文件等),后端可以是参考实现 Marquez,也可以是 DataHub 等元数据平台。

落地时要注意

  • 数据集命名要统一:同一张表在 Spark、Flink、Trino 里必须生成相同的 namespace 和 name,否则血缘连不起来;
  • 采集覆盖率要验证:某些自定义 Source、UDF、外部系统写入可能提取不到,要做覆盖率统计;
  • 监听器不能影响作业:上报要异步,失败不能导致作业失败,大作业的执行计划解析要注意开销;
  • 和 SQL 解析互补:OpenLineage 拿运行时血缘,SQL 解析可以在上线前做静态分析,两者结合效果最好。