2. 数据质量校验体系架构

上一章我们聊了为什么要做数据质量,这一章直接上干货——体系架构怎么搭。

说实话,我见过太多团队一上来就写规则、跑脚本,结果三个月后规则堆成山,跑完也不知道有没有用。为什么?因为缺了架构。没有架构的质量校验,就像没有图纸盖楼,早晚得塌。

我个人习惯把数据质量校验体系拆成四个核心部分:分层架构、元数据驱动、规则引擎、告警与修复闭环。这四个东西串起来,才是一个能自运转的体系。

一、分层架构设计:别让所有校验挤在一层

先看这张图,这是我常用的四层校验架构:

数据质量校验分层架构图 数据质量校验分层架构 第1层:源端校验 数据接入前,在源系统或采集层完成基础校验 第2层:存储层校验 数据入仓/入湖后,对表结构、分区、元数据做校验 第3层:计算层校验 ETL/数仓建模过程中,对中间表、宽表做规则校验 第4层:应用层校验 数据输出前,对报表、接口、下游消费做最终校验 💡 每一层校验失败,都应阻断数据流向下一层,避免脏数据扩散

为什么要分层?我举个例子。以前有个项目,ETL 跑完才发现源端字段类型变了,整张表全挂。如果源端校验层能提前拦住,后面根本不会出问题。分层的好处就是:早发现、早阻断、少浪费。

层级 校验时机 典型规则 阻断策略
源端校验 数据采集/接入时 字段类型、非空、主键唯一 拒绝接入,告警源端负责人
存储层校验 入仓/入湖后 分区完整性、Schema 一致性 标记异常分区,不参与下游计算
计算层校验 ETL 过程中 数据量波动、聚合值范围、关联丢失 中断任务,回滚至上一正常版本
应用层校验 数据输出前 报表指标一致性、接口响应格式 拦截输出,触发人工审核
我的经验:不要试图在每一层都做全量校验。源端做轻量快速校验,计算层做深度业务校验,应用层做最终把关。分层不是堆规则,是分职责。

二、元数据驱动:让规则自己找到目标

规则多了怎么管理?靠人肉维护?不现实。我见过一个团队,3000 多条规则,每次新增表都要手动配一遍,配完还经常漏。后来我帮他们改成元数据驱动,规则自动匹配,效率翻了三倍。

元数据驱动的核心思路是:把规则定义成模板,通过元数据自动绑定到目标表或字段。

举个例子:

-- 元数据表:质量规则模板
CREATE TABLE quality_rule_template (
    rule_id        STRING  COMMENT '规则ID',
    rule_name      STRING  COMMENT '规则名称',
    rule_type      STRING  COMMENT '规则类型:非空/唯一/范围/枚举',
    rule_expr      STRING  COMMENT '规则表达式,如 IS NOT NULL',
    scope_level    STRING  COMMENT '作用域:表级/字段级',
    severity       STRING  COMMENT '严重级别:P0/P1/P2'
);

-- 元数据表:字段与规则绑定
CREATE TABLE quality_rule_binding (
    binding_id     STRING  COMMENT '绑定ID',
    table_name     STRING  COMMENT '表名',
    column_name    STRING  COMMENT '字段名',
    rule_id        STRING  COMMENT '规则ID',
    is_active      BOOLEAN COMMENT '是否启用'
);

这样设计后,新增一张表只需要在元数据系统里注册表结构,规则引擎自动根据字段类型、命名规范匹配规则模板。比如所有 id 结尾的字段自动绑定非空+唯一规则,所有 amount 字段自动绑定数值范围规则。

关键点:元数据驱动不是一次性工作。表结构变更、字段废弃、规则升级,都要通过元数据变更流程联动。我曾经踩过一个坑——字段改名了,元数据没更新,规则跑了一周全报错。后来加了元数据变更监听,自动刷新绑定关系。

三、规则引擎:别写死,要可配置

规则引擎是整个体系的大脑。我见过最糟糕的做法是把规则写在 ETL 脚本里,改一条规则要改代码、重新部署、重启任务。你想想看,这得多痛苦。

好的规则引擎应该具备三个能力:

  • 规则可配置:通过界面或 API 增删改规则,不需要改代码
  • 规则可编排:支持规则组合、优先级、依赖关系
  • 规则可扩展:支持自定义函数、外部字典、模型调用

我常用的规则引擎架构是这样的:

规则引擎核心流程 规则引擎核心流程 数据输入 待校验数据集 规则解析器 加载规则模板 规则执行器 逐条执行校验 结果 通过/失败 规则库 存储规则定义 元数据 表结构/字段信息 💡 规则引擎从规则库加载规则,从元数据获取目标信息,动态生成校验任务
避坑指南:我曾经把规则引擎做得太灵活,允许用户写任意 SQL 片段。结果有人写了一条 DELETE FROM table 当规则……嗯,从那以后我强制规则引擎只允许读操作,所有写操作必须走审批流程。

四、告警与修复闭环:发现问题只是开始

很多团队把数据质量做成「发现问题→发告警→没人管→下次继续告警」的死循环。说白了,只做了前半段,没做后半段。

一个完整的闭环应该包含:

  1. 告警分级:P0 问题直接电话+短信+群@所有人,P2 问题发邮件就行。别让所有告警都变成「狼来了」。
  2. 自动修复:对于已知的、可修复的问题(比如重跑、补数),让系统自动执行修复脚本。
  3. 人工介入:自动修复失败或无法自动修复的,升级到人工处理,并记录处理过程。
  4. 复盘改进:每次修复后,分析根因,更新规则或元数据,避免同类问题再次发生。

我习惯用一张表来跟踪闭环状态:

-- 质量事件跟踪表
CREATE TABLE quality_event_tracking (
    event_id        STRING   COMMENT '事件ID',
    rule_id         STRING   COMMENT '触发的规则ID',
    table_name      STRING   COMMENT '问题表',
    severity        STRING   COMMENT '严重级别',
    status          STRING   COMMENT '状态:NEW/FIXING/FIXED/CLOSED',
    auto_fix_action STRING   COMMENT '自动修复动作',
    manual_comment  STRING   COMMENT '人工备注',
    created_at      TIMESTAMP,
    closed_at       TIMESTAMP
);
核心原则:告警不是终点,修复才是。我要求团队每个质量事件必须在 24 小时内进入「FIXING」状态,否则自动升级到技术负责人。别让问题过夜,过夜的问题往往会变成历史遗留问题。

好了,这一章的内容就这些。分层架构让你知道校验该放在哪,元数据驱动让规则自动匹配,规则引擎让校验可配置可扩展,告警与修复闭环让问题真正被解决。这四个东西缺一不可,少了任何一个,体系都会出现短板。