4、数据源接入与元数据管理:如何对接Hive、Kafka、MySQL等数据源,构建统一的元数据中心
数据质量看板,说白了就是“数据的数据”在说话。你连源头的数据长什么样都不清楚,后面的质量规则、监控告警全是空中楼阁。
我刚开始做数据治理那会儿,接过一个项目。业务方说“我们数据都在Hive里”,结果一查,Hive表有三千多张,一半没有注释,字段命名全靠猜。更头疼的是,实时数据走Kafka,业务库还有MySQL分库分表。三个数据源,三种元数据格式,怎么统一?
嗯,这就是我们今天要聊的核心——数据源接入与元数据管理。
4.1 元数据中心:为什么你需要一个“数据的地图”
元数据是什么?就是描述数据的数据。表名、字段名、类型、分区、主键、更新时间、数据量……这些信息构成了你理解数据的基础。
没有元数据中心,你会遇到什么?
- 开发问:“这个字段是啥意思?”——没人知道。
- 运维问:“这张表数据量多大?”——得跑一遍count。
- 分析师问:“数据从哪来的?”——查半天链路。
我个人习惯,在搭建数据质量看板之前,先搭元数据中心。哪怕初期只接入核心表,也比没有强。
4.2 数据源接入:三种典型场景的实战方案
我们团队对接过的主流数据源,无非三类:离线数仓(Hive)、实时消息(Kafka)、关系型数据库(MySQL)。每种接入方式都不一样,我一个个说。
4.2.1 对接Hive:元数据藏在Hive Metastore里
Hive的元数据,其实都存储在Metastore中。Metastore背后通常是MySQL或PostgreSQL。你直接连Metastore的库,就能拿到所有表结构信息。
我在项目中遇到过一个问题:Metastore里存的字段类型是Hive内部的字符串表示,比如array<string>、struct<id:int,name:string>。解析起来有点麻烦。我的做法是写一个轻量级的解析器,把复杂类型拆成扁平结构,方便后续存储和展示。
-- 示例:查询Hive Metastore获取表字段信息
SELECT
d.NAME AS database_name,
t.TBL_NAME AS table_name,
c.COLUMN_NAME,
c.TYPE_NAME,
c.INTEGER_IDX AS col_order,
t.TBL_ID
FROM
TBLS t
JOIN DBS d ON t.DB_ID = d.DB_ID
JOIN COLUMNS_V2 c ON t.TBL_ID = c.CD_ID
WHERE
d.NAME = 'your_database'
AND t.TBL_NAME = 'your_table'
ORDER BY
c.INTEGER_IDX;
PARTITIONS和PARTITION_KEYS表中。如果你需要监控分区数据是否准时到达,记得把分区字段也拉入元数据中心。
4.2.2 对接Kafka:Schema Registry是你的好朋友
Kafka的数据是流式的,没有固定的“表结构”。但实际生产中,消息都有Schema。要么是Avro,要么是Protobuf,要么是JSON Schema。
我个人强烈建议使用Confluent Schema Registry。它统一管理Kafka消息的Schema,并且支持兼容性检查。你只需要调用它的REST API,就能拿到每个Topic的字段定义。
# 示例:通过Schema Registry API获取Topic的Schema
GET /subjects/{subject_name}/versions/latest
# 返回示例(Avro Schema)
{
"subject": "user_click-value",
"version": 3,
"id": 101,
"schema": "{\"type\":\"record\",\"name\":\"UserClick\",\"fields\":[{\"name\":\"user_id\",\"type\":\"string\"},{\"name\":\"click_time\",\"type\":\"long\"},{\"name\":\"page_id\",\"type\":\"int\"}]}"
}
我曾经踩过一个坑:某个Topic的Schema升级了,加了新字段,但下游消费者没更新。结果数据反序列化失败,整条链路断了。后来我在元数据中心里加了一个Schema版本变更记录表,每次变更都触发告警,通知相关方。
4.2.3 对接MySQL:直接查INFORMATION_SCHEMA
MySQL的元数据获取最简单。每个MySQL实例都有INFORMATION_SCHEMA库,里面存了所有表、字段、索引、约束的信息。
但要注意,INFORMATION_SCHEMA在表多的时候查询很慢。我遇到过一张库里有5000多张表,直接SELECT * FROM TABLES卡了十几秒。后来我改成按库名过滤,分批拉取。
-- 示例:获取指定数据库的所有表及字段信息
SELECT
t.TABLE_NAME,
t.TABLE_ROWS,
t.AUTO_INCREMENT,
c.COLUMN_NAME,
c.DATA_TYPE,
c.IS_NULLABLE,
c.COLUMN_DEFAULT,
c.CHARACTER_MAXIMUM_LENGTH
FROM
INFORMATION_SCHEMA.TABLES t
JOIN INFORMATION_SCHEMA.COLUMNS c
ON t.TABLE_NAME = c.TABLE_NAME
AND t.TABLE_SCHEMA = c.TABLE_SCHEMA
WHERE
t.TABLE_SCHEMA = 'your_database'
AND t.TABLE_TYPE = 'BASE TABLE'
ORDER BY
t.TABLE_NAME, c.ORDINAL_POSITION;
4.3 统一元数据模型:怎么把“三张皮”缝成一件衣服
Hive、Kafka、MySQL的元数据格式完全不同。Hive有数据库、表、分区;Kafka有Topic、Schema、分区;MySQL有库、表、字段、索引。怎么统一?
我的做法是设计一个通用元数据模型,把不同数据源的元数据映射成统一的结构。
| 数据源类型 | 源对象 | 映射到统一模型 | 关键属性 |
|---|---|---|---|
| Hive | 数据库.表 | Catalog.Schema.Table | 存储格式、分区字段、文件数 |
| Kafka | Topic | Catalog.Schema.Topic | 分区数、副本数、消息保留时间 |
| MySQL | 数据库.表 | Catalog.Schema.Table | 引擎、自增ID、索引信息 |
统一模型的核心字段包括:
- catalog:数据源实例标识,比如“hive_prod”、“kafka_online”
- schema:命名空间,Hive的数据库、Kafka的集群、MySQL的库
- entity:实体名,表或Topic
- entity_type:TABLE / TOPIC / VIEW
- fields:字段列表,每个字段包含name、type、description、nullable
- properties:扩展属性,JSON格式,存放各数据源特有的信息
你想想看,有了这个统一模型,你的数据质量看板就可以一套规则引擎处理所有数据源。不管是Hive表字段非空校验,还是Kafka消息Schema兼容性检查,底层都是同一个元数据接口。
4.4 元数据采集与同步:增量还是全量?
元数据不是一成不变的。Hive表会新增分区,Kafka Topic会升级Schema,MySQL表会加字段。所以你需要一个定时采集+增量更新的机制。
我个人习惯的做法:
- 首次全量采集:把所有数据源的元数据拉一遍,存入元数据中心。
- 定时增量采集:每隔5-10分钟,对比上次采集时间,只拉取变更的部分。
- 变更事件推送:如果数据源支持事件通知(比如MySQL的Binlog、Kafka的Schema变更事件),优先用事件驱动,实时更新。
TBL_ID是递增的,MySQL的UPDATE_TIME字段可以判断表是否变更。Kafka Schema Registry每次注册新版本都会递增version。
4.5 整体架构:一张图看懂元数据中心
说了这么多,我们来画一张架构图。这张图展示了我常用的元数据中心设计,包括数据源接入层、采集层、存储层和服务层。
4.6 落地避坑:我踩过的三个坑
最后,分享几个我在元数据中心落地过程中踩过的坑,希望能帮你少走弯路。
我曾经把Hive Metastore的采集频率设成1分钟一次。结果Metastore的MySQL连接数被打满,Hive查询都受影响。后来改成10分钟一次,加上增量对比,问题解决。
元数据采集只拉了字段名和类型,没拉注释。结果数据质量看板上线后,业务方看着“col_1”、“col_2”一脸懵。后来我强制要求每个字段必须有描述,否则标记为“待补充”。
Kafka Schema升级后,我检查了兼容性,但没通知下游。结果消费者消费失败,数据延迟了2小时才发现。后来我加了Webhook,Schema变更自动发到企业。