面试官问OLAP引擎,你只说'查询快'就完了?——Doris架构和MPP原理
本文目录
先说结论
Doris是一个基于MPP架构的实时分析型数据库。核心由FE(前端节点,负责SQL解析、查询规划、元数据管理)和BE(后端节点,负责数据存储和查询执行)组成。数据按列存储、分区分桶分布在多个BE节点上,查询时所有BE并行计算,汇总结果返回。
面试答架构要讲清楚三个层面:① 宏观架构(FE+BE的角色和协作);② MPP为什么快(和MapReduce的区别);③ 列式存储为什么适合分析查询。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
面试官问Doris架构,不是让你说'FE和BE两个组件'就完了。他想听的是:MPP架构为什么快?和Hadoop MapReduce有什么本质区别?FE和BE分别干什么、怎么配合?你们生产环境怎么部署的?我在某元宇宙社交公司从0搭建Flink+Doris实时数仓,从选型到部署到调优都亲手做过,今天把Doris架构讲透。
FE和BE的角色分工
Doris的架构非常简洁,只有两种节点,没有外部依赖(不需要HDFS、ZooKeeper),这也是它运维简单的核心原因之一:
# Doris集群架构
#
# 客户端(MySQL协议)
# ↓
# ┌──────────────────────────┐
# │ FE 集群(Frontend) │
# │ ┌────┐ ┌────┐ ┌────┐ │
# │ │ FE │ │ FE │ │ FE │ │ ← Master + Follower + Observer
# │ │Lead│ │Fol │ │Obs │ │ ← 元数据管理、SQL解析、查询规划
# │ └────┘ └────┘ └────┘ │
# └──────────────────────────┘
# ↓ 分发查询计划
# ┌──────────────────────────┐
# │ BE 集群(Backend) │
# │ ┌────┐ ┌────┐ ┌────┐ │
# │ │ BE │ │ BE │ │ BE │ │ ← 数据存储 + 查询执行
# │ └────┘ └────┘ └────┘ │
# └──────────────────────────┘
| 组件 | 角色 | 核心职责 | 部署建议 |
|---|---|---|---|
| FE Master | 主节点 | 元数据写入、查询规划、协调 | 1个(高可用配3个FE) |
| FE Follower | 从节点 | 元数据同步、可做查询入口 | 2个(和Master组成3节点高可用) |
| FE Observer | 观察者 | 只读元数据、分担查询压力 | 按需添加 |
| BE | 计算+存储节点 | 存储数据、执行查询计划 | ≥3个(和数据量成正比) |
关键特点:① 兼容MySQL协议——用MySQL客户端就能连,DBA和业务同事零学习成本;② 没有外部依赖——不需要HDFS、ZooKeeper、YARN,部署和运维极其简单;③ FE的元数据用Raft协议同步(类似KRaft),保证高可用。
MPP架构为什么快?——和MapReduce的本质区别
MPP(Massively Parallel Processing,大规模并行处理)是Doris快的核心原因。面试官最喜欢问的追问就是:MPP和MapReduce有什么区别?
| 维度 | MPP(Doris) | MapReduce(Hive/Spark) |
|---|---|---|
| 执行模式 | 所有节点同时计算,流水线式传输 | 按Stage串行执行,Shuffle落盘 |
| 中间数据 | 内存中流式传输,不落盘 | Shuffle必须写磁盘再读取 |
| 查询延迟 | 秒级到亚秒级 | 分钟级到小时级 |
| 适合场景 | 交互式即时查询 | 大规模批处理ETL |
| 数据规模 | 适合TB级别 | 适合PB级别 |
| 容错性 | 一个节点挂了整个查询失败 | Task失败可以重试 |
一句话总结:MPP是所有节点同时并行计算,数据在内存中流式传输;MapReduce是按Stage串行执行,中间数据要Shuffle落盘。MPP牺牲了一定的容错性和数据规模上限,换来了极致的查询速度。
# MPP查询执行过程(以Doris为例)
#
# SELECT country, SUM(amount) FROM orders GROUP BY country
#
# 1. FE收到SQL → 解析 → 生成分布式查询计划
# 2. FE把查询计划分发给所有BE节点
# 3. 每个BE并行扫描自己本地的数据分片
# BE-0: 扫描Partition-0的数据,本地做GROUP BY聚合
# BE-1: 扫描Partition-1的数据,本地做GROUP BY聚合
# BE-2: 扫描Partition-2的数据,本地做GROUP BY聚合
# 4. 各BE的局部聚合结果通过网络汇总到一个BE
# 5. 汇总节点做最终聚合,返回结果给FE
#
# 全程数据在内存中流转,不落盘!
# 3个BE并行扫描,速度是单节点的约3倍
列式存储为什么适合分析查询?
Doris底层数据按列存储(Columnar Storage),这是OLAP引擎快的另一个关键原因。面试经常追问:列式存储为什么比行式存储快?
| 维度 | 行式存储(MySQL) | 列式存储(Doris) |
|---|---|---|
| 存储方式 | 一行的所有列存在一起 | 同一列的所有值存在一起 |
| 查询模式 | 适合按主键查单行(OLTP) | 适合扫描某几列做聚合(OLAP) |
| IO效率 | 查1列也要读整行所有列 | 只读需要的列,IO大幅减少 |
| 压缩率 | 不同列类型混在一起,压缩率低 | 同类型数据压缩率极高(5-10倍) |
| 写入模式 | 单行插入快 | 批量导入快,单行插入慢 |
-- 举个具体例子:一张有50个字段的订单表
-- 行式存储(MySQL):
-- SELECT SUM(amount) FROM orders WHERE dt = '2024-01-15'
-- 需要读取整行50个字段的数据,即使只需要amount和dt两列
-- 假设一行500字节,1亿行 = 50GB IO
-- 列式存储(Doris):
-- 同样的查询,只读amount列(8字节)+ dt列(4字节)
-- 1亿行 × 12字节 = 1.2GB IO
-- 再加上列式压缩(通常5-10倍),实际IO约120-240MB
-- IO量是行式存储的1/200到1/400!
-- 这就是为什么同样的聚合查询
-- MySQL要跑30秒,Doris只需要0.5秒
实战经验:我在某元宇宙社交公司的Doris部署
在某元宇宙社交公司,我从0搭建了Doris集群,作为实时数仓的查询层。当时的部署方案:
集群规模:3个FE节点(1 Master + 2 Follower,保证高可用)+ 3个BE节点(每台32核128GB内存、2TB SSD)。
数据量:核心表约20张,最大的用户行为明细表日增5000万条,总数据量约2TB。
查询性能:实时大盘的聚合查询(UV/PV/GMV)平均响应时间800ms,复杂的多表JOIN查询在3秒内返回。相比之前用Hive查同样的数据需要几分钟,提升非常明显。
写入方式:Flink消费Kafka后通过Stream Load写入Doris,攒批1000条或5秒一批。写入吞吐稳定在5000条/秒以上。
面试高频追问
追问一:FE Master挂了怎么办?
如果部署了3个FE节点(1 Master + 2 Follower),Master挂了会自动通过Raft协议选举新Master,过程通常在秒级完成,客户端几乎无感知。如果只有1个FE就是单点故障,生产环境必须至少3个FE。Observer不参与选举,只分担查询压力。
追问二:Doris兼容MySQL协议是什么意思?
意味着你可以用MySQL客户端、JDBC驱动、Navicat等任何MySQL工具直接连接Doris。SQL语法也高度兼容MySQL。这对运维和业务同事非常友好——不用学新工具,用他们已经熟悉的MySQL客户端就能查数据。我们团队的产品经理和运营同事都是直接用Metabase连Doris看数据的。
追问三:MPP架构的最大缺点是什么?
两个主要缺点:① 容错性差——一个BE挂了整个查询就失败了(MapReduce的Task失败可以重试);② 并发瓶颈——MPP的查询会用到所有节点,高并发时每个查询都抢所有节点的资源,容易互相影响。一般Doris的并发能力在50-100 QPS左右(复杂查询),高并发场景需要配合缓存或物化视图。
实战踩坑:BE内存不够导致大查询失败
在某元宇宙社交公司刚上线Doris的第一个月,有一次运营同事跑了一个没加WHERE条件的全表扫描查询(SELECT * FROM user_events),3个BE节点的内存全部打满,不仅这个查询失败了,还把其他人的查询全部拖慢了。
这就是MPP架构的特点——一个查询的执行涉及所有BE节点。一个重查询可以拖垮整个集群。
-- 解决方案:给Doris设置查询资源限制
-- 1. 设置单个查询的内存上限
SET exec_mem_limit = 4294967296; -- 4GB
-- 2. 设置查询超时时间
SET query_timeout = 60; -- 60秒
-- 3. 更好的方案:使用Resource Group(Doris 2.0+)
-- 给不同用户分配不同的资源配额
CREATE WORKLOAD GROUP 'analyst'
PROPERTIES (
'cpu_share' = '10',
'memory_limit' = '30%',
'max_concurrency' = '10'
);
-- 分析师的查询最多用30%内存,避免影响实时大盘
教训:MPP引擎必须做资源隔离。不同优先级的查询(实时大盘 vs 临时分析)要分到不同的资源组,避免互相影响。这个经验我后来带到了每一个用OLAP引擎的项目。
总结
Doris架构面试要讲清楚三个层面:① FE+BE的分工(FE管元数据和SQL解析,BE管存储和计算);② MPP为什么快(全节点并行+内存流式传输,不像MapReduce要Shuffle落盘);③ 列式存储为什么适合分析(只读需要的列,IO减少几百倍)。能结合实际部署经验说出集群规模、查询性能数字和踩过的坑,面试官就知道你是真正用过Doris的人,而不是背八股文。
下一篇聊Doris的数据模型:同一张表该选Duplicate、Aggregate还是Unique?选错了性能差10倍。
你们生产环境用的什么OLAP引擎?集群多大?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长