3、数据契约定义与规范:契约定义语言(CDL)、字段命名规范、数据类型映射、元数据标签体系

数据契约这东西,说白了就是给实时数仓立规矩。没有规矩,你想想看,上游随便改个字段类型,下游直接崩掉。我在项目里见过太多次这种惨案了。所以这一章,咱们就把契约的定义、命名、映射和标签体系彻底讲透。

3.1 契约定义语言(CDL)

CDL 不是什么新语言,而是一套轻量级的 YAML/JSON 规范。我个人习惯用 YAML,可读性更好。一个完整的 CDL 文件长这样:

# 数据契约定义示例
contract:
  version: "1.0"
  domain: "order"
  dataset: "order_detail"
  owner: "data-platform@company.com"

schema:
  - name: order_id
    type: string
    description: "订单唯一标识"
    constraints:
      - not_null
      - unique
  - name: user_id
    type: string
    description: "用户ID"
    constraints:
      - not_null
  - name: amount
    type: decimal(18,2)
    description: "订单金额"
    constraints:
      - not_null
      - min: 0

producer:
  system: "order_service"
  topic: "ods_order_detail"
  partition: 12
  retention: "7d"

consumer:
  - system: "flink_dwd"
    usage: "实时宽表加工"
  - system: "clickhouse"
    usage: "实时报表查询"

quality:
  - metric: "null_rate"
    threshold: 0.01
  - metric: "duplicate_rate"
    threshold: 0.001

这里有几个关键点:

  • version:契约版本号,每次变更必须升级
  • producer/consumer:明确谁生产、谁消费
  • quality:数据质量阈值,这是实时数仓的生命线
我曾经踩过一个坑:契约里没写 retention,结果上游 topic 数据只保留 24 小时,下游离线任务跑批时数据已经过期了。从那以后,我强制所有 CDL 必须包含 retention 字段。

3.2 字段命名规范

命名规范这事,看起来简单,做起来全是坑。我见过一个项目,字段名有驼峰、有下划线、有匈牙利命名法,混在一起简直灾难。我的建议是:

3.2.1 核心原则

  • 全小写 + 下划线:这是 Flink 和 Kafka 生态的通用做法
  • 业务前缀:比如订单域用 ord_,用户域用 usr_
  • 避免缩写歧义:create_time 不要写成 crt_tm

3.2.2 分层命名示例

分层 命名规则 示例
ODS ods_{源系统}_{表名} ods_mysql_order_detail
DWD dwd_{业务域}_{主题} dwd_order_payment_rt
DWS dws_{业务域}_{维度}_{指标} dws_order_daily_summary
ADS ads_{应用}_{场景} ads_realtime_dashboard
小技巧:字段名长度控制在 30 个字符以内。太长的话,Kafka schema registry 和 Flink 状态后端都会有点吃不消。

3.3 数据类型映射

实时数仓里,数据类型映射是最容易出问题的地方。MySQL 的 DECIMAL 到 Flink 的 DECIMAL,看起来一样,精度却可能丢失。我整理了一份常用映射表:

MySQL 类型 Flink SQL 类型 Kafka Avro 类型 注意事项
INT INT int 无符号类型需转为 BIGINT
BIGINT BIGINT long 注意溢出问题
DECIMAL(p,s) DECIMAL(p,s) bytes(decimal) 精度 p 最大 38
VARCHAR(n) STRING string Flink 无长度限制
DATETIME TIMESTAMP(3) string(iso8601) 时区统一用 UTC
JSON STRING string Flink 1.15+ 支持原生 JSON
核心原则:所有时间字段统一使用 TIMESTAMP(3) 类型,时区固定为 UTC+0。下游消费时再根据业务需求转换。这样可以避免跨时区带来的各种诡异问题。

3.4 元数据标签体系

元数据标签,说白了就是给数据打上各种标记,方便管理和检索。我习惯把标签分为三类:

3.4.1 技术标签

  • 数据源:mysql、kafka、log、binlog
  • 采集方式:全量、增量、CDC
  • 存储引擎:HDFS、Kafka、ClickHouse
  • 压缩格式:snappy、gzip、lz4

3.4.2 业务标签

  • 业务域:订单、支付、用户、商品
  • 数据等级:核心、重要、一般
  • 敏感等级:P0(公开)、P1(内部)、P2(敏感)、P3(机密)
  • 生命周期:热数据、温数据、冷数据

3.4.3 治理标签

  • 质量状态:正常、告警、阻塞
  • 负责人:团队或个人
  • SLA 等级:99.9%、99.99%
  • 审计状态:未审计、已审计、待复核

这些标签最终会写入元数据中心,比如 Apache Atlas 或自研的元数据平台。每次数据流转时,标签会自动继承和更新。

注意:标签不是越多越好。我见过一个团队给一张表打了 50 多个标签,结果维护成本比数据本身还高。建议每张表不超过 10 个核心标签。

3.5 数据契约全流程

说了这么多,咱们用一张图把整个流程串起来:

数据契约全流程 CDL 定义 Schema Registry 数据生产 质量校验 元数据采集 标签体系 数据消费 说明: 1. CDL 定义完成后,自动注册到 Schema Registry 2. 数据生产时实时校验质量,不合格数据进入死信队列 3. 元数据采集和标签体系为数据消费提供治理基础

这张图展示了数据契约从定义到消费的完整链路。核心在于:契约先行,校验紧随,标签兜底。没有契约,实时数仓就是一团乱麻。

我的经验:刚开始推行数据契约时,团队会觉得麻烦。但坚持一个月后,你会发现线上故障减少了 80%。这就是规矩的力量。