Doris 的外表元数据同步机制是怎样的?对于外部元数据或物理数据的变更,Doris 是如何进行近实时感知的(例如通过 Event Receiver 进行 DDL 变更同步)?
Apache Doris 的外表(External Table)元数据同步机制,是其 Multi-Catalog 架构的核心能力之一。为了在保证查询高性能的同时,尽可能降低由于外部数据源(如 Hive, Iceberg, Hudi 等)元数据或物理数据变更带来的“数据不一致”问题,Doris 设计了一套多层次、动静结合的元数据同步与感知机制。
以下是 Doris 外表元数据同步机制的详细解析,重点介绍如何通过 HMS Event Listener(Event Receiver) 实现近实时的 DDL/DML 变更感知。
一、 Doris 外表元数据管理架构概述
在 Doris 中,外表元数据由 Frontend (FE) 统一管理:
- Catalog 层:Doris 引入了 Multi-Catalog,将外部数据源(如 Hive Metastore, Iceberg REST, Glue 等)映射为一个 Catalog。
- 元数据缓存(Metadata Cache):为了避免每次查询都去请求外部数据源(这会非常慢),FE 会将外表的 Database、Table、Schema、Partition 以及具体的 File List (文件列表) 缓存到内存中。
- 痛点:一旦外部数据源发生变更(如 Spark 删除了分区、Hive 新增了列、Flink 写入了新文件),Doris 缓存的元数据就会失效,导致查询报错或结果不准确。
二、 近实时感知:基于 HMS Event Listener 的自动同步
这是 Doris 实现近实时(Near Real-Time, 秒级延迟)感知外部 DDL/DML 变更的核心机制。它主要针对支持 Hive Metastore (HMS) 协议的数据源(如 Hive, Hudi, 采用 HMS 的 Iceberg)。
1. 工作原理与架构
该机制采用 “拉取(Polling)+ 事件驱动(Event-Driven)” 的模式:
[外部引擎 (Spark/Flink)]
│ (执行 DDL/DML)
▼
[ Hive Metastore (HMS) ] ────► 写入 HMS RDBMS (如 MySQL 的 NOTIFICATION_LOG 表)
▲
│ 1. 轮询获取事件 (get_next_notification)
[ Doris FE (Event Receiver Thread) ]
│ 2. 解析事件 (CREATE/DROP/ALTER/INSERT)
▼
[ Doris 元数据缓存 (Catalog/Schema/File Cache) ] ───► 3. 失效或更新缓存
2. 关键组件与步骤
- HMS 端(事件源):
Hive Metastore 必须配置DbNotificationListener。当外部引擎(Spark, Hive CLI, Flink 等)对 Hive 表进行操作时,HMS 会捕获这些事件,并持久化到其后台关系型数据库的NOTIFICATION_LOG表中。 - Doris FE 端(Event Receiver 线程):
Doris FE 后台启动了一个轻量级的同步线程(Event Receiver)。该线程会定期(默认 10 秒)调用 HMS 的get_next_notification接口,根据上一次处理的Event ID,增量拉取最新的元数据变更事件。 - 事件映射与缓存更新策略:
Doris 收到事件后,不会盲目重建整个 Catalog,而是精准失效(Invalidate)或更新特定的缓存:
| HMS 事件类型 | 触发的操作 | Doris FE 中的应对策略 |
|---|---|---|
| CREATE_TABLE | 外部新建表 | 在 Doris 对应的 Database 下新增该表元数据(Lazy 加载,不立即读文件) |
| DROP_TABLE | 外部删除表 | 直接将 Doris 内存中对应的 Table 缓存清除 |
| ALTER_TABLE | 外部修改表(加列、改列等) | 清除该表的 Schema 缓存,下次查询时重新从 HMS 加载最新 Schema |
| ADD_PARTITION | 外部新增分区(如按天分区) | 清除该表的 Partition 缓存,重新加载分区列表 |
| DROP_PARTITION | 外部删除分区 | 移除 Doris 内存中对应的分区及文件缓存 |
| ALTER_PARTITION | 分区属性变更 | 清除该分区的元数据缓存 |
| INSERT | 外部写入新数据(DML) | 非常关键:清除该表或该分区的 File List 缓存,下次查询重新列出(List)HDFS/S3 文件 |
3. 如何开启此功能?
在创建 Doris Catalog 时,通过设置属性开启:
CREATE CATALOG hive PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://10.16.1.1:9083',
-- 开启自动同步
'enable.metastore.event.active.sync' = 'true',
-- 事件轮询间隔(秒)
'event.sync.interval.seconds' = '10'
);
三、 物理数据变更的感知(File List 级别)
DDL 变更通常改变的是 Schema 结构,而 DML 变更(如 Spark 追加了 10 个 Parquet 文件)改变的是物理数据。Doris 如何感知这些物理文件的增加、删除或修改?
- 通过
INSERT事件感知(如上所述):
当外部引擎通过 HMS 写入数据时,会产生INSERT或ALTER_PARTITION事件。Doris 收到后,会使该分区下的 File Cache(文件缓存) 失效。下一次查询该分区时,Doris FE 会重新调用 HDFS API 或 S3 API 获取最新的文件列表。 - Iceberg / Hudi 的特殊机制(版本/Snapshot 感知):
对于现代表格式(Iceberg/Hudi),它们本身不依赖 HMS 记录文件列表,而是有自己的Metadata JSON或Timeline。- Iceberg:Doris 缓存的是 Iceberg 表的
Current Snapshot ID。当查询发生时,Doris 会快速请求 Iceberg 的 Catalog 校验 Snapshot ID 是否发生变化。如果有新 Snapshot,Doris 只拉取新旧 Snapshot 的差量文件,无需重扫描。 - Hudi:类似于 Iceberg,Doris 会校验 Hudi 的
Instant Time(时间线),感知是否有新的 Commit,从而更新文件列表。
- Iceberg:Doris 缓存的是 Iceberg 表的
四、 其他辅助元数据同步机制(非实时/兜底)
除了基于 Event 的近实时感知,Doris 还提供了其他机制作为互补:
1. 手动刷新(Manual Refresh)
当发生重大变更,或者未使用 HMS(如直接对接 S3 上的普通文件,或使用 JDBC Catalog)时,可以使用手动命令。这是最强力的硬刷新:
-- 刷新整个 Catalog
REFRESH CATALOG hive_catalog;
-- 只刷新某个数据库
REFRESH DATABASE hive_catalog.db_name;
-- 只刷新某张表
REFRESH TABLE hive_catalog.db_name.table_name;
原理:清空对应的所有缓存,下次查询时全部重新从外部数据源拉取。
2. 定时自动刷新(Auto Schema Syncer)
对于不支持 Event Listener 的 Catalog(如 JDBC Catalog 映射的 MySQL 库),Doris 提供了后台定时轮询任务:
- 可以配置定时任务,每隔一段时间(如 1 小时)自动执行
REFRESH操作,自动同步外部表结构的变化。
3. 缓存自动过期(TTL)
Doris 对元数据缓存设置了有效期。
- 可以通过配置 FE 参数
meta_cache_expiry_sec(默认不开启,或设为较长值)。在缓存过期后,Doris 会重新从外部拉取。但在实际生产中,为了查询性能,更推荐使用 Event Sync 配合较长(甚至永久)的缓存时间。
五、 总结与最佳实践
Doris 的外表元数据同步机制可以总结为:“事件驱动为主(近实时),手动刷新为辅(强一致兜底)”。
| 场景 | 推荐机制 | 延迟性 | 性能影响 |
|---|---|---|---|
| Hive / Hudi / Iceberg (基于 HMS) | 开启 HMS Event Active Sync | 秒级(10s 内) | 极低(仅增量失效缓存,无冗余拉取) |
| Iceberg (基于 REST/Glue) | Snapshot 校验机制 | 毫秒级(查询时校验) | 极低 |
| JDBC Catalog (MySQL/Oracle) | 定时自动刷新 或 手动刷新 | 分钟级/天级 | 中等 |
| 元数据严重不一致/排查问题 | 手动 REFRESH TABLE |
0 延迟(立即生效) | 高(触发全面重新加载) |
通过这套机制,Doris 在 Multi-Catalog 极速分析的同时,解决了外表元数据漂移的问题,保证了极高的数据一致性。