ODS/DWD/DWS/ADS全建在Doris里?——实时数仓分层实践
本文目录
先说结论
实时数仓不是把所有层都搬到Doris里。最佳实践是:Kafka做ODS层(原始数据缓冲)、Flink做实时ETL(DWD/DWS加工)、Doris做查询层(DWD明细查询+DWS/ADS汇总查询)。大量历史数据的存储底座还是用S3/HDFS+Hive/Spark。
核心原则:Doris负责'热数据'的实时查询(最近7-30天),Hive/S3负责'冷数据'的长期存储和复杂ETL。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
实时数仓分层是面试的经典题目,但如果你说的分层和Hive离线数仓一模一样,面试官就会追问:实时数仓和离线数仓的分层有什么区别?所有层都建在Doris里吗?什么数据适合放Doris什么适合放Hive?我在某元宇宙社交公司搭建过Flink+Kafka+Doris的实时数仓,在某短剧出海公司用过Hologres+MaxCompute的混合架构,今天把两种实践经验对比着讲清楚。
实时数仓分层 vs 离线数仓分层
| 层级 | 离线数仓(Hive) | 实时数仓(Doris) | 区别 |
|---|---|---|---|
| ODS | HDFS/S3原始文件 | Kafka Topic | 实时数仓ODS在Kafka里,不在Doris |
| DWD | Hive表,T+1产出 | Doris Duplicate表,秒级写入 | 实时数仓DWD是秒级更新的 |
| DWS | Hive聚合表,T+1产出 | Doris Aggregate/物化视图 | 实时数仓DWS接近实时 |
| ADS | Hive应用表/导出MySQL | Doris表直接查/接口服务 | 不需要导出,Doris自己就能服务查询 |
| DIM | Hive维度表/MySQL | Doris Unique表+CDC同步 | 实时数仓维度表也是实时更新的 |
我在某元宇宙社交公司的实时数仓分层
# 实时数仓完整架构
#
# ┌─ ODS层(Kafka)─────────────────────────┐
# │ user_event Topic ← 埋点SDK实时写入 │
# │ gift_txn Topic ← FlinkCDC从MySQL同步 │
# │ user_sync Topic ← FlinkCDC用户维度同步 │
# └────────────────────────────────────────┘
# ↓ Flink DataStream消费+ETL
# ┌─ DWD层(Doris Duplicate表)───────────────┐
# │ dwd_user_event ← 清洗后的用户行为明细 │
# │ dwd_gift_txn ← 清洗后的交易明细 │
# └────────────────────────────────────────┘
# ↓ Doris物化视图 / Flink聚合
# ┌─ DWS层(Doris Aggregate/物化视图)────────┐
# │ dws_daily_overview ← 每日UV/PV/GMV汇总 │
# │ mv_country_stats ← 按国家的物化视图 │
# └────────────────────────────────────────┘
# ↓ 直接查询
# ┌─ ADS层(Doris表 / Metabase大盘)──────────┐
# │ 实时大盘(Metabase连接Doris) │
# │ 运营后台(API查询Doris) │
# └────────────────────────────────────────┘
#
# ┌─ DIM层(Doris Unique表)──────────────────┐
# │ dim_user ← FlinkCDC实时同步 │
# │ dim_gift ← FlinkCDC实时同步 │
# └────────────────────────────────────────┘
每一层在Doris里用什么数据模型?
| 层级 | 表名 | Doris模型 | 原因 |
|---|---|---|---|
| DWD | dwd_user_event | Duplicate | 保留所有明细,支持多维分析 |
| DWD | dwd_gift_txn | Unique | 按transaction_id去重,支持状态更新 |
| DWS | dws_daily_overview | Aggregate | 按天预聚合,查询极快 |
| DIM | dim_user | Unique | 按user_id更新最新状态 |
| DIM | dim_gift | Unique | 按gift_id更新配置信息 |
Doris数仓 vs 传统Hive数仓的核心区别
① 实时性:Hive数仓是T+1(昨天的数据今天才能看),Doris数仓是秒级(数据写入后立刻可查)。这对运营和投放决策意义重大——在某短剧出海公司,投手需要5分钟内看到广告效果数据,T+1是完全不可接受的。
② DWS层的实现方式不同:Hive的DWS层需要跑Spark/Hive SQL调度任务来聚合,Doris的DWS层可以用Aggregate模型或物化视图自动完成预聚合,不需要额外的调度任务。
③ ADS层直接服务查询:Hive的ADS层数据通常要导出到MySQL才能给业务系统用,Doris本身就支持高并发查询(兼容MySQL协议),ADS层数据直接在Doris里查就行,不需要再导出。
④ 维度表实时更新:Hive的维度表是T+1更新(每天跑一次全量覆盖),Doris的Unique模型+FlinkCDC可以做到秒级更新——用户改了昵称,几秒后Doris里的dim_user就更新了。
实战经验:两家公司的不同分层实践对比
| 维度 | 某元宇宙社交公司 | 某短剧出海公司 |
|---|---|---|
| ODS | Kafka(自建集群) | Kafka(阿里云托管) |
| ETL引擎 | Flink DataStream | Flink + DataWorks调度 |
| DWD/DWS存储 | Doris(自建) | Hologres(阿里云托管) |
| 离线存储 | S3 | MaxCompute |
| BI工具 | Metabase | 云厂商BI工具 |
| 数据时效 | 秒级 | 5分钟 |
| 数据规模 | 日增5000万条 | 日增数亿条 |
两家公司架构思路一样,只是技术栈不同(自建 vs 云服务)。核心分层逻辑完全一致:Kafka做缓冲→Flink做ETL→OLAP引擎做查询→BI展示。
实战踩坑:全量数据都放Doris导致存储爆了
在某元宇宙社交公司刚搭实时数仓时,我把所有历史数据(半年的用户行为明细,约500GB)都导入了Doris。结果3个BE节点的2TB SSD磁盘占了70%,而且越来越多。
问题:Doris用本地SSD存储,成本远高于S3/HDFS。半年的历史数据大部分是冷数据(很少被查询),放在Doris里纯粹浪费昂贵的SSD空间。
解决方案:Doris只保留最近30天的热数据(用动态分区自动删除30天前的分区),历史数据存在S3上。需要查历史数据时用Spark读S3,或者用Doris的Multi-Catalog功能直接查S3上的Parquet文件(查询速度比本地慢但能查到)。
-- 动态分区:自动保留30天数据
ALTER TABLE dwd_user_event SET (
'dynamic_partition.enable' = 'true',
'dynamic_partition.time_unit' = 'DAY',
'dynamic_partition.start' = '-30', -- 只保留30天
'dynamic_partition.end' = '3',
'dynamic_partition.prefix' = 'p',
'dynamic_partition.buckets' = '16'
);
-- Doris Multi-Catalog查询S3上的历史数据(Doris 2.0+)
CREATE CATALOG s3_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://hms-host:9083'
);
-- 直接查S3上的Hive/Parquet表
SELECT * FROM s3_catalog.mydb.user_event_history
WHERE dt = '2023-06-15';
教训:Doris不是万能的存储引擎。热数据放Doris(SSD高速查询),冷数据放S3/HDFS(低成本存储),用Doris的Multi-Catalog打通冷热数据查询。这才是成本和性能的最优平衡。
面试高频追问
追问一:实时数仓还需要离线数仓吗?
需要。实时数仓和离线数仓互补而非替代。实时数仓解决'快'的问题(秒级/分钟级),离线数仓解决'全'和'准'的问题(全量历史数据、复杂ETL、数据回刷)。我在元宇宙社交公司是实时数仓(Doris)和离线数仓(S3+Spark)并存的。
追问二:Doris能替代Hive做数仓底座吗?
TB级别可以,PB级别不行。Doris的存储成本比Hive高(SSD vs HDFS/S3),而且Doris不太适合做超大规模的ETL计算(MPP对复杂ETL不如Spark灵活)。最佳实践是Doris做查询加速层,Hive做存储底座。
追问三:DWS层用物化视图还是建独立的Aggregate表?
简单聚合用物化视图(自动维护,省心),复杂ETL用独立的Aggregate表+Flink/调度任务。我的经验是:能用物化视图搞定的就不建独立表,减少维护成本。但涉及多表JOIN的复杂聚合,物化视图搞不定,就要建独立的DWS表。
总结
实时数仓分层面试讲清楚三点:① 和离线数仓的区别(ODS在Kafka不在HDFS、DWS可以用物化视图自动预聚合、ADS直接查Doris不用导出MySQL);② 每层用什么Doris数据模型(DWD用Duplicate/Unique、DWS用Aggregate/物化视图、DIM用Unique);③ 冷热分离(Doris存热数据30天、S3/HDFS存冷数据、Multi-Catalog打通查询)。能结合两家公司的对比经验讲,面试官会觉得你对实时数仓有深度理解。
下一篇聊Doris的查询优化实战:慢查询怎么排查?EXPLAIN怎么看?常见的优化套路有哪些?
你们的实时数仓分层是什么样的?所有层都在Doris里吗?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长
Doris 面试通关手册
第11-15篇:运维调优与安全治理
Wood聊大数据
9年大数据老兵,聊技术、聊职场、聊成长