大数据Doris初识
前言
Github:https://github.com/HealerJean
一、Apache Doris 简介
介绍:Apache Doris 是一款基于 MPP (Massively Parallel Processing) 大规模并行处理 架构的高性能、实时分析型数据库。它以高效、简单和统一的特性著称,能够在亚秒级 (小于 1 秒但大于 1 微秒) 的时间内返回海量数据的查询结果。Doris 既能支持高并发的点查询场景,也能支持高吞吐的复杂分析场景。
典型场景:基于这些优势,Apache Doris 非常适合用于报表分析、即席查询、统一数仓构建、数据湖联邦查询加速等场景。用户可以基于 Doris 构建大屏看板、用户行为分析、AB 实验平台、日志检索分析、用户画像分析、订单分析等应用。
二、发展历程
Apache Doris 最初是百度广告报表业务的 Palo 项目。2017 年正式对外开源,
2018 年 7 月由百度捐赠给 Apache 基金会进行孵化。在 Apache 导师的指导下,由孵化器项目管理委员会成员进行孵化和运营。
2022 年 6 月,Apache Doris 成功从 Apache 孵化器毕业,正式成为 Apache 顶级项目(Top-Level Project,TLP)。
目前,Apache Doris 社区已经聚集了来自不同行业数百家企业的 600 余位贡献者,并且每月活跃贡献者人数超过 120 位。
三、应用现状
Apache Doris 在中国乃至全球范围内拥有广泛的用户群体。截至目前,Apache Doris 已经在全球超过 4000 家中大型企业的生产环境中得到应用。
在中国市值或估值排行前 50 的互联网公司中,有超过 80% 长期使用 Apache Doris,包括百度、美团、小米、京东、字节跳动、阿里巴巴、腾讯、网易、快手、微博等。同时,在金融、消费、电信、工业制造、能源、医疗、政务等传统行业也有着丰富的应用。
在中国,几乎所有的云厂商,如阿里云、华为云、天翼云、腾讯云、百度云、火山引擎等,都在提供托管的 Apache Doris 云服务。
四、使用场景
数据源经过各种数据集成和加工处理后,通常会进入实时数据仓库
Doris和离线湖仓(如Hive、Iceberg和Hudi),广泛应用于OLAP分析场景,ApacheDoris主要应用于以下场景:
1、实时数据分析:
- 实时报表与实时决策: 为企业内外部提供实时更新的报表和仪表盘,支持自动化流程中的实时决策需求。
- 交互式探索分析: 提供多维数据分析能力,支持对数据进行快速的商业智能分析和即席查询(Ad Hoc),帮助用户在复杂数据中快速发现洞察。
- 用户行为与画像分析: 分析用户参与、留存、转化等行为,支持人群洞察和人群圈选等画像分析场景。
2、湖仓融合分析:
- 湖仓查询加速: 通过高效的查询引擎加速湖仓数据的查询。
- 多源联邦分析: 支持跨多个数据源的联邦查询,简化架构并消除数据孤岛。
- 实时数据处理: 结合实时数据流和批量数据的处理能力,满足高并发和低延迟的复杂业务需求。
3、半结构化数据分析:
- 日志与事件分析: 对分布式系统中的日志和事件数据进行实时或批量分析,帮助定位问题和优化性能。
五、整体架构
ApacheDoris采用MySQL协议,高度兼容MySQL语法,支持标准SQL。用户可以通过各类客户端工具访问ApacheDoris,并支持与BI工具无缝集成。
1、存算一体
Frontend (FE): 主要负责接收用户请求、查询解析和规划、元数据管理以及节点管理,包含3个角色。
Backend (BE): 负责物理数据的存储和计算。数据会被切分成数据分片(Shard),在BE中以多副本方式存储。
FE和BE进程都可以横向扩展。单个集群可以支持数百台机器和数十PB的存储容量。FE和BE进程通过一致性协议来保证服务的高可用性和数据的高可靠性。存算一体架构高度集成,大幅降低了分布式系统的运维成本。

2、存储引擎
在存储引擎方面,
ApacheDoris采用列式存储,按列进行数据的编码、压缩和读取,能够实现极高的压缩比,同时减少大量非相关数据的扫描,从而更有效地利用IO和CPU资源。
1)基本情况
a、索引结构
ApacheDoris也支持多种索引结构,以减少数据的扫描:
SortedCompoundKeyIndex: 最多可以指定三个列组成复合排序键。通过该索引,能够有效进行数据裁剪,从而更好地支持高并发的报表场景。Min/MaxIndex: 有效过滤数值类型的等值和范围查询。BloomFilterIndex: 对高基数列的等值过滤裁剪非常有效。InvertedIndex: 能够对任意字段实现快速检索。
b、存储模型
在存储模型方面,
ApacheDoris支持多种存储模型,针对不同的场景做了针对性的优化:
- 明细模型(
DuplicateKeyModel): 适用于事实表的明细数据存储。 - 主键模型(
UniqueKeyModel): 保证Key的唯一性,相同Key的数据会被覆盖,从而实现行级别数据更新。 - 聚合模型(
AggregateKeyModel): 相同Key的Value列会被合并,通过提前聚合大幅提升性能。
c、其他
Apache Doris 也支持强一致的单表物化视图和异步刷新的多表物化视图。单表物化视图在系统中自动刷新和维护,无需用户手动选择。多表物化视图可以借助集群内的调度或集群外的调度工具定时刷新,从而降低数据建模的复杂性。
2)存储流程
INSERT INTO sales VALUES (1, 100.0);
BE 处理流程
FELeader解析SQL,确定数据应写入的BE节点(如根据Hash分桶)。- 数据分发:导入任务首先将数据分发到所有相关的
BE节点。 - 并行写入:各个
BE节点并行处理数据写入操作。 - 写入确认:每个
BE节点在完成数据写入后,会向FE发送确认信息。 - 多数派判断:
FE统计成功写入的副本数,当达到多数派时,认为导入成功。 - 事务提交:
FE提交导入事务,使数据对外可见。 - 异步复制:对于未成功写入的副本,系统会在后台异步进行数据复制,以确保最终所有副本的数据一致性。
多数派写入策略是 Doris 在数据可靠性和系统可用性之间的一个平衡。对于有特殊需求的场景,Doris 提供了最小写入副本数等其他选项来进一步提高系统的灵活性。
3、查询引擎
ApacheDoris采用大规模并行处理(MPP)架构,支持节点间和节点内并行执行,以及多个大型表的分布式ShuffleJoin,从而更好地应对复杂查询。

1)查询流程
a、Query(用户发起查询)
-
节点选择:用户客户端 →
FE含义:用户通过
MySQL协议向Doris前端(Frontend)发送SQL查询请求 -
内部处理
- 查询首先到达
Frontend的QueryPlanner组件 - 不涉及具体节点选择,是查询流程的起点
- 查询首先到达
b、Send fragment(发送查询片段)
- 节点选择:
Frontend→Backend - 含义:
QueryCoordinator将优化后的查询计划拆分为多个可并行执行的Fragment(片段)
c、Fully MPP distributed(完全 MPP 分布式执行)
-
节点选择:
Backend↔Backend -
含义:各
BE节点并行执行分配的Fragment,并通过网络交换中间数据关键点
- 节点间通过
Shuffle进行数据重分布(如HashShuffle、Broadcast等)
- 节点间通过
d、Results(返回部分结果)
- 节点选择:
Backend→Frontend - 含义:各
BE节点将部分计算结果返回给Frontend - 关键点
- 不是所有
BE都直接返回给用户,而是先汇总到Frontend - 对于聚合查询,可能包含本地聚合结果
- 不是所有
e、Return results(返回最终结果)
- 节点选择:
Frontend→ 用户客户端 - 含义:前端将最终结果集返回给用户
- 关键点:前端
QueryCoordinator组件负责最终汇总
2)查询案例-1
分析2023年双十一期间,各地区的销售额Top 5商品
SELECT
region,
product_id,
SUM(amount) AS total_sales
FROM orders
WHERE order_date BETWEEN '2023-11-11' AND '2023-11-12'
GROUP BY region, product_id
ORDER BY total_sales DESC
LIMIT 5
a、Query 接收阶段
- 用户通过
MySQL客户端发送SQL到Frontend QueryPlanner组件:- 解析
SQL生成语法树 - 检查元数据(
orders表的region/product_id/amount字段) - 识别分区键(
order_date)进行分区剪枝
- 解析
b、计划生成与分发
QueryPlanner生成分布式执行计划:
Fragment 1: Scan orders表(带日期过滤)
Fragment 2: Hash Aggregate(按 region + product_id 分组求和)
Fragment 3: Merge Aggregate + TopN排序
QueryCoordinator将Fragment分发:-
Fragment1-1/1-2/1-3:分配到存储orders表不同分片的3个BE节点 -
Fragment2-1/2-2:分配到2个计算节点 Fragment3-1:单独一个节点做最终聚合
c、分布式执行阶段
-
BE节点并行执行-
Fragment1-x节点:`(存储节点):过滤日期- 扫描本地Tablet
- 应用日期过滤条件
-
输出符合条件的数据
-
# 伪代码示例 for tablet in tablets: if tablet.contains('2023-11-11'): scan_data = columnar_scan(tablet) filtered = apply_predicate(scan_data) # 过滤日期 send_to(Fragment2, hash(region,product_id))
-
Fragment2-x节点:计算节点-
接收来自多个Fragment1-x的数据
-
按(region, product_id)分组求和
-
输出部分聚合结果
-
receive_data = shuffle_receive(hash_key) local_agg = hash_aggregate(receive_data) # 本地聚合 send_to(Fragment3, all_data)
-
-
d、结果收集
Fragment3-1节点:(汇总节点):- 接收所有
Fragment2节点的预聚合结果 - 执行最终聚合(相同分组求和)
- 应用
TopN排序(全局排序取前5) - 将结果返回
Frontend
- 接收所有
e、结果返回
Frontend将最终结果集返回客户端:
region | product_id | total_sales
----------+------------+------------
华东地区 | P10086 | 1258000.00
华南地区 | P10032 | 987600.00
华北地区 | P10045 | 876500.00
华东地区 | P10092 | 765300.00
西南地区 | P10012 | 687900.00

3)FQA
a、逻辑表与物理存储的关系:
-
用户看到的
orders表是逻辑整体 -
物理存储被自动分片(
Tablet)并分布在多个BE节点 -
示例分片分布:
orders表 ├─ Tablet01 (存储2023-11-01到2023-11-10数据) → BE1 ├─ Tablet02 (存储2023-11-11到2023-11-20数据) → BE2 └─ Tablet03 (存储2023-11-21到2023-11-30数据) → BE3 Tablet是分桶的物理实现:每个分桶文件就是一个数据分片(Tablet),Tablet是数据划分的最小逻辑单元,也是数据移动、复制等操作的最小物理存储单元3。各个Tablet之间的数据没有交集,并且在物理上是独立存储的。- 分桶决定
Tablet 的分布和数量:用户可以指定一个或多个维度列以及桶数对数据进行HASH分布,从而将数据均匀地分布到不同的桶中,每个桶对应一个Tablet4。在Doris中,表的总Tablet数等于分区数乘以每个分区的桶数2。例如,如果一个表有10个分区,每个分区有16个桶,那么该表就有160个Tablet。
b、存储分片规则可视化

c、Fragment 的角色分工
-
阶段1:分布式扫描(
Fragment1):负责数据扫描和基础过滤(如日期过滤)-
每个
BE只扫描本地存储的分片(数据本地化) -
自动跳过不包含目标日期的分片(分区剪枝)
-
- 阶段2:分布式聚合(
Fragment2):负责分布式聚合计算- 相同 (
region,product_id) 的数据被Shuffle到同一个BE节点 - 图中
Fragment 2-1和2-2并行处理不同哈希桶的数据
- 相同 (
- 阶段3:结果合并(
Fragment3):负责最终结果合并

d、为什么过滤和计算要分开?
1、数据本地化原则(Where过滤)
-
存储节点执行过滤的优势:
-
减少网络传输(先过滤再传输)
-
利用本地存储索引加速过滤
-
图中
Fragment1-1/1-2/1-3在不同BE节点并行扫描和过滤
- 计算专业化原则(聚合计算)
- 专用计算节点的优势:
- 聚合计算需要更多
CPU资源 - 避免与
I/O操作竞争资源 - 您图中
Fragment2-1/2-2是专门负责聚合的计算节点
- 聚合计算需要更多
e、汇总职责到底谁来承担

问题1:Query Coordinator(FE)的汇总职责 是什么?
- 全局结果收集,负责接收所有
BE节点返回的最终结果片段,并将其合并为完整的查询结果返回给客户端,若查询涉及多个Fragment 3-1实例(并行执行),FE会整合这些实例的结果(如合并排序后的TopN结果)
问题2:Fragment 3-1(BE)的汇总职责 是什么?
-
中间结果聚合:负责将下层
Fragment(如Fragment 2-x的哈希聚合结果)进行跨节点合并(MergeAggregate)和排序(TopN)例如:Fragment 2-1和Fragment 2-2分别计算了(region, product_id)的部分聚合结果,Fragment 3-1会将这些部分结果进一步合并为全局聚合值 -
数据本地化处理:在
BE节点本地完成计算,减少FE的计算压力。FE仅需接收最终精简后的数据
问题3:为什么要两层汇总?
-
避免单点瓶颈:若仅依赖
FE汇总,所有中间结果需传输到FE,网络和计算压力集中 -
MPP架构优势:BE节点的并行计算能力(如Fragment 3-1的合并)显著提升大规模数据处理的效率 -
职责分离:
-
FE专注查询调度和元数据管理,汇总是 是逻辑上的最终结果组装,不涉及数据计算 -
BE专注数据计算和存储,符合Doris的存算一体设计原则,汇总是物理上的数据聚合与排序,属于分布式计算的一部分。两者协同实现高效查询,而非功能重
-
f、Query Planner 和 Query Coordinator
问题1:各自的职责分别是什么?
| 模块 | Query Planner |
Query Coordinator |
|---|---|---|
| 主要职责 | 生成逻辑和物理执行计划(优化查询路径) | 调度执行计划,协调 BE 节点执行并合并结果 |
| 工作阶段 | 查询编译阶段(SQL解析→优化→生成 Plan Fragment) |
查询执行阶段(任务分发→进度监控→结果合并) |
| 关键技术 | 基于 CBO / RBO 优化器、谓词下推、分区裁剪等 |
分布式任务调度、两阶段聚合、容错重试 |
| 是否同一节点 | 是(均位于 FE 节点内,但逻辑分层) |
是( Coordinator 是 FE 的核心模块之一)* |

问题2:FE 内部任务分配—-> Query Coordinator 协调器是怎么选中的:
答案:FE 收到请求后,会根据 负载均衡 选自身或其他 FE 当 Coordinator (也可能直接自己干 )简单说:FE 谁先接到请求、谁负载低、谁元数据全,谁就更可能当查询 Coordinator ,Leader/Follower 因元数据强一致,是 “优先候选”,Observer 是 “补充候选
六、组件介绍
1、FE 3 种角色
在生产环境中,可以部署多个
FE节点以实现容灾备份。每个FE节点都会维护完整的元数据副本。FE节点分为以下三种角色:
-
Leader:FEMaster节点负责元数据的读写。当Master节点的元数据发生变更后,会通过BDBJE协议同步给Follower或Observer节点。 -
Follower:Follower节点负责读取元数据。当Master节点发生故障时,可以选取一个Follower节点作为新的Master节点。 -
Observer:Observer节点负责读取元数据,主要目的是增加集群的查询并发能力。Observer节点不参与集群的选主过程。
一般情况下,每台 FE 节点可以负责 10-20 台 BE 节点的负载操作,3 个 FE 节点可以满足大部分的业务需求。
| 维度 | Leader |
Follower |
Observer |
|---|---|---|---|
| 核心职责 | 唯一可写入元数据的节点 | 同步 Leader 元数据 |
异步同步元数据 - |
| 节点负责元数据的读写 | 处理读请求 | 处理读请求 | |
| 管理集群状态与节点选举 | 参与 Leader 选举 |
不参与选举 | |
| 元数据同步方式 | 主动写入元数据 | 强同步:Raft 协议实时同步 Leader 元数据 |
异步同步:定期拉取 Leader 元数据(秒级延迟) |
通过 Raft 协议同步给 Follower |
|||
| 读写权限 | 可读可写 | 只读(不可直接写入元数据) | 只读 |
| 选举能力 | 由 Follower 选举产生,故障时可被替换 |
可参与选举,能成为新 Leader |
不参与选举,无法成为 Leader |
| 数据一致性 | 元数据最新版本 | 与 Leader 强一致(多数派确认后提交) |
最终一致(可能存在短暂延迟) |
| 性能影响 | 写入时需等待 Follower ACK,可能受网络影响 |
消耗 Leader 同步资源(带宽 / CPU) |
对 Leader 无额外负载,可扩展读能力 |
| 典型场景 | 核心业务写入 | 热备节点 | 报表分析 |
| 高可用集群主节点 | 强一致读请求 | 读密集型查询 | |
| 元数据管理 | 故障切换保障 | 减轻主集群压力 | |
| 推荐节点 | 1 个(建议部署在高可用硬件上) |
2~3 个(满足 Raft 多数派) |
按需扩展(5~20 个,视读负载而定) |
| 扩展性 | 1个 | 有限(奇数,通常≤3) | 无限(按需扩展) |
| 资源开销 | 高(元数据同步+选举) | 低(仅元数据同步) |
1)角色关系与工作流程
1. 写入流程(以创建表为例):
Client → Leader(创建表元数据) → Raft 日志 → Follower1, Follower2(多数派 ACK) → 写入成功
↓(异步线程)
Observer1, Observer2(拉取元数据更新)
2. 读流程(以查询表为例):
Client → Follower/Observer(读取元数据) → 若为 Observer,可能存在延迟(需等待元数据同步)
2)为何需要两种读节点?
Doris设计Follower和Observer是为了平衡 可用性 与 扩展性:
Follower是 “可靠的副本”, 是Raft共识的参与者,通过强一致性协议保证元数据与Leader实时同步,确保故障时能无缝接管集群,适用于所有对元数据准确性要求高的读取场景。。Observer是 “高效的扩展”,是Raft共识的旁观者,通过牺牲强一致性(允许秒级延迟)换取读能力扩展,适用于对元数据实时性不敏感的分析场景。适合分析型场景(如电商大盘数据统计,允许秒级延迟)。
3)Follower 与 Leader 的强一致性
解释:通过 Raft 协议的 多数派确认机制 保障一致性:例如 3 个 Follower 中,Leader 需至少收到 2 个 Follower 的 ACK 才提交写入,避免脑裂场景下的数据不一致。少数节点的 “不同意”(如故障、延迟、日志不一致)只是暂时状态,通过日志同步机制最终会被修复。
典型场景:金融交易系统查询订单表,要求实时看到最新创建的表结构,必须连接 Leader 或 Follower
4)Observer 的扩展性优势
无状态扩展:Observer 不参与 Raft 共识,可无限扩展(如 50 个节点),适合海量读请求场景(如每日亿级次报表查询)。
延迟容忍场景:例如电商平台的用户行为分析,允许新创建的分析表在 3 秒后被查询到,可通过 Observer 承载这类请求。
问题1:什么时候可以决定使用 Observer
答案:客户端主动配置 + FE 自动调度 + 业务场景适配 ,三者结合决定是否用 Observer 。
- 如果是高并发、非实时的读请求,优先往
Observer上引; - 如果是实时性要求高的,必须走
Leader/Follower~

5)Follower 的限制
必须奇数且数量有限:
选举与高可用要求:,需满足奇数数量(如1、3、5个)以保证选举的多数决机制
- 部署 1 个
Follower:仅实现读高可用(无选举容灾能力)。- 部署 3 个
Follower:实现读写高可用(Leader故障时可自动切换)
- 性能瓶颈:所有
Follower需实时同步Leader的元数据变更(如DDL、导入事务),Follower越多,日志复制延迟风险越高,可能拖慢集群响应速度 - 选举复杂度:
Follower数量过多会降低选举效率,增加故障恢复时间 -
运维成本:奇数数量的
Follower需跨故障域部署(如不同机架),无限扩展会大幅提升部署和监控成本 - 建议数量:
- 官方推荐生产环境部署
3个Follower(满足高可用)和1-3个Observer(扩展读能力),而非无限扩展Follower - 在线业务:
3Follower+NObserver(保障HA和读扩展) - 离线业务:
1Follower+NObserver(节省资源)
- 官方推荐生产环境部署
6)建表流程
CREATE TABLE sales (
id INT,
amount DOUBLE
) DISTRIBUTED BY HASH(id) BUCKETS 10;
FE 处理流程
- 客户端发送
SQL到FELeader。 Leader将CREATE TABLE转为元数据日志,写入本地Raft日志。Leader通过Raft复制日志到所有Follower,等待多数派(如 3 节点中的 2 个)确认。- 多数派确认后,
Leader提交日志,更新内存中的表结构,并返回成功给客户端。 Follower收到提交通知后,应用日志到本地元数据。
2、FE和 ** 和 **BE 节点 差异
在
Doris中,FE(前端)节点 和BE(后端)节点 的一致性保障机制存在本质差异,这是理解分布式系统设计的关键。以下从架构、协议、数据类型和应用场景四个维度详细解释:
1)架构分层:元数据与业务数据的分离
Doris 采用 元数据与业务数据分离存储 的架构:
FE节点:管理集群元数据(如数据库 / 表结构、权限、节点状态),所有元数据变更通过Raft协议强一致同步。BE节点:存储实际业务数据(如用户订单、商品信息),数据多副本通过P2P协议同步,一致性级别可配置。
这种分离的好处是:
- 元数据强一致保障系统稳定性(如建表操作必须全局一致)。
- 业务数据根据场景调整一致性(如实时交易需强一致,离线分析可接受最终一致)。
2)一致性协议对比
| 维度 | FE 节点(元数据) | BE 节点(业务数据) |
|---|---|---|
| 一致性协议 | Raft(强一致性) |
Paxos(可配置一致性级别) |
| 核心流程 | Leader 写入→多数派 Follower 确认→提交 |
FE 直接分发数据→各 BE 并行写入→直接返回 FE 确认 |
| 确认机制 | 必须多数派(≥N/2+1)确认才能提交 | 可配置(QUORUM/ALL/ASYNC) |
| 故障恢复 | 自动选举新 Leader,强制同步日志 |
副本丢失后自动重建(从其他副本拉取数据) |
| 典型延迟 | 毫秒级(取决于网络 RTT) |
亚秒级至秒级(取决于数据量和网络状况) |
3)为什么设计两种一致性模型?
a、元数据必须强一致:
- 元数据是集群的 “控制平面”,若不一致会导致严重问题(如
FE节点对表结构认知不同,查询报错)。 Raft协议通过多数派确认和日志强制同步,确保元数据全局一致,即使节点故障也能自动恢复。
b、业务数据可按需调整:
- 强一致场景(如金融交易):写
ALL或QUORUM副本,确保数据不丢失,但牺牲写入性能。 - 最终一致场景(如用户行为日志):异步复制,写入性能高,但可能在故障时丢失少量未同步数据(主副本故障会丢)。
4)BE:读取模式区别
QUORUM(多数派读写):当使用QUORUM模式时,Doris在读操作时会从多个副本中读取,并确保大多数副本的数据一致才返回结果。写操作则要求数据被复制到大多数副本上。-
优点:提供了较好的一致性和可用性保证。即使部分副本不可用,只要大多数副本正常工作,系统仍能提供服务。
-
缺点:相比
ASYNC模式,可能会稍微降低一些性能,因为它需要等待多个副本响应。
-
-
ALL(全量读写):在ALL模式下,所有的读写操作都需要涉及到的所有副本都成功才能完成。这意味着对于读操作,必须从所有副本获取数据并确认它们是一致的;对于写操作,则需要确保数据被成功写入所有副本。-
优点:提供了最强的一致性保证,因为所有副本的数据都是同步更新的。
-
缺点:如果有一个副本出现问题或延迟,整个操作将会受到影响,可能导致较高的延迟甚至失败。因此,这种模式通常用于对一致性要求极高的场景。
-
ASYNC(异步读写):使用ASYNC模式 (默认)时,读操作可以从任意一个副本执行,而不需要检查其他副本的状态。写操作则是异步地将数据复制到其他副本上。- 优点:
- 高性能:由于不需要等待所有副本的数据同步完成即可进行读取,因此能够提供较低的延迟和较高的吞吐量。
- 最终一致性:在写入后立即执行的读取可能会遇到旧数据,但随着时间推移,所有副本将最终达到一致状态。
- 缺点:牺牲了一定程度的一致性,因为在写入后立即进行读取可能不会得到最新的数据,直到所有副本都被更新为止。适用于那些可以容忍一定程度数据不一致的应用场景。
六、Apache Doris 的核心特性
高可用: Apache Doris 的元数据和数据均采用多副本存储,并通过 Quorum 协议同步数据日志。当大多数副本完成写入后,即认为数据写入成功,从而确保即使少数节点发生故障,集群仍能保持可用性。 Apache Doris 支持同城和异地容灾,能够实现双集群主备模式。当部分节点发生异常时,集群可以自动隔离故障节点,避免影响整体集群的可用性。
高兼容: Apache Doris 高度兼容 MySQL 协议,支持标准 SQL语法,涵盖绝大部分 MySQL 和 Hive 函数。通过这种高兼容性,用户可以无缝迁移和集成现有的应用和工具。Apache Doris 支持 MySQL 生态,用户可以通过 MySQL 客户端工具连接 Doris,使得操作和维护更加便捷。同时,可以使用 MySQL 协议对 BI 报表工具与数据传输工具进行兼容适配,确保数据分析和数据传输过程中的高效性和稳定性。
实时数仓: 基于 Apache Doris 可以构建实时数据仓库服务。Apache Doris 提供了秒级数据入库能力,上游在线联机事务库中的增量变更可以秒级捕获到 Doris 中。依靠向量化引擎、MPP 架构及 Pipeline 执行引擎等加速手段,可以提供亚秒级数据查询能力,从而构建高性能、低延迟的实时数仓平台。
湖仓一体: Apache Doris 可以基于外部数据源(如数据湖或关系型数据库)构建湖仓一体架构,从而解决数据在数据湖和数据仓库之间无缝集成和自由流动的问题(统一计算层 + 多源存储适配 + 智能数据路由 三大核心技术,实现湖仓间的数据无缝集成与自由流动。以下是具体实现方式:),帮助用户直接利用数据仓库的能力来解决数据湖中的数据分析问题,同时充分利用数据湖的数据管理能力来提升数据的价值。
灵活建模:Apache Doris 提供多种建模方式,如宽表模型、预聚合模型、星型/雪花模型等。数据导入时,可以通过 Flink、Spark 等计算引擎将数据打平成宽表写入到 Doris 中,也可以将数据直接导入到 Doris 中,通过视图、物化视图或实时多表关联等方式进行数据的建模操作。
七、FAQ
1、为什么不能直接替换 MySQL
1)核心优势场景
- 海量数据分析:10PB 级存储 + 亚秒级查询(聚合 / OLAP 场景),适合数据仓库、BI 报表、实时分析。
MySQL协议兼容:无缝对接现有 MySQL 生态工具(如 Navicat、Sqlyog),降低迁移成本。- 极简架构:无复杂组件依赖(对比 Hadoop 生态),运维成本低,适合快速迭代的业务。
2)不可忽视的边界
- 事务支持有限:仅支持单表主键唯一性约束,不支持跨表事务(对比
MySQLInnoDB)。 - 非结构化数据处理弱:无法直接处理文档、图片等非结构化数据(需预处理)。
- 实时写入性能瓶颈:高并发小批量写入(如每秒 10 万 + 单条记录)时效率低于专用实时系统(存储原因导致)。
| 维度 | MySQL(OLTP) | Apache Doris(OLAP) |
|---|---|---|
| 数据模型 | 行存为主,支持复杂事务和索引 | 列存为主,面向分析场景优化 |
| 写入模式 | 支持实时增删改(ACID 保障) |
批量导入为主(支持分区级更新) |
| 查询场景 | 低延迟单条 / 小批量数据查询 | 大规模聚合、多维度分析查询 |
| 典型场景 | 订单系统、用户中心等核心业务 | 订单统计报表、用户行为分析 |
2、和 mysql 正确协同方式是什么?
1、正确的协同方式:MySQL 处理实时交易,Doris 负责历史数据聚合分析,通过中间件同步数据。
业务系统(MySQL) → 数据同步(Canal/MaxCompute) → Doris(分析层)
2、读写分离优化:高频查询(如最近 7 天数据)仍由 MySQL 承担,历史数据(>30 天)迁移至 Doris 降低 MySQL 负载。
3、Doris 与 ES / ``HBase`
1)对比 Elasticsearch(ES)
ES的不可替代性:- 全文检索:分词、模糊查询、相关性排序(如电商搜索、日志分析)。
- 半结构化数据:
JSON文档灵活存储(如用户画像标签、传感器数据)。 - 实时数据流处理:配合
Logstash/Kafka实现秒级索引更新。
Doris的适配场景:- 当
ES查询变慢时:Doris可承接ES中聚合分析需求(如 “按地区统计搜索频次”),ES专注全文检索。 - 多维度分析:
ES擅长 “找数据”,Doris擅长 “算数据”,两者结合实现 “搜索 + 分析” 闭环。
- 当
| 维度 | Elasticsearch |
Apache Doris |
|---|---|---|
| 数据存储 | 倒排索引(适合检索)+ 列式存储(部分版本) | 列式存储(按列压缩,分析场景优化) |
| 计算引擎 | 单节点串行计算为主(可分布式但协调开销大) | 向量化执行引擎 + 分布式 MPP 架构(并行计算) |
| 聚合优化 | 依赖分片合并,易出现 “热分片” | 分区裁剪 + 谓词下推 + 聚合下推,减少数据扫描量 |
| 典型场景 | 数据量较小(亿级以下)+ 简单聚合 | 海量数据 + 复杂聚合 |
| 聚合结果需与检索条件强绑定 | 多表关联聚合 | |
需要 SQL 兼容与生态工具 |
日志分析场景
ES快速定位具体日志,Doris提供趋势分析,两者互补。
日志采集 → Kafka → Flink(清洗) → 双写:
- ES(实时检索)
- Doris(聚合分析,如“按小时统计错误日志占比”)
2)**Doris **对比 HBase
-
HBase的核心能力:- 超大规模稀疏数据:
PB级非结构化数据存储(如物联网设备日志、用户行为轨迹)。 - 高并发随机读写:支持每秒百万级单条记录读写(如实时推荐系统的特征存储)。
- 灵活
schema:列族设计支持动态添加列(适合快速迭代的业务)。
- 超大规模稀疏数据:
-
Doris与HBase的协同:HBase存储原始数据,Doris作为分析层:
设备数据 → HBase(实时写入) → 定期同步至Doris(离线分析)HBase+Doris联合查询:通过外表功能(Doris1.2+)直接查询HBase数据,避免数据冗余。
电商平台架构
Doris的角色:承接Flink计算结果,提供多维度分析(如 “按地域 + 时间 + 商品类目统计GMV”)。
[业务层] MySQL(订单交易) + Redis(缓存)
[实时层] Kafka(数据流) + Flink(实时计算) + ES(商品搜索)
[分析层] Doris(用户行为分析、订单统计) + Hive(离线数仓)
[存储层] HBase(用户画像标签) + 对象存储(图片/视频)
附录
1、元数据
元数据是 “关于数据的数据”,它不直接存储业务数据,而是记录数据的 “属性信息”,类似于图书的目录、作者、分类等描述性内容。在
Doris中,元数据由FE(Frontend)节点集中管理,是整个集群运行的 “大脑中枢”。
- 数据结构元数据
- 表与字段定义:记录表的名称、字段类型(
INT、STRING等)、字段注释、主键约束等。 - 分区与分桶信息:例如表按时间字段(
date)分区,或按哈希值分桶存储,用于优化查询性能。 - 视图与函数定义:用户创建的视图逻辑、自定义函数(
UDF)的元数据信息。
- 集群运行元数据
- 节点状态:各
FE、BE(Backend)节点的在线状态、IP地址、资源占用情况。 - 数据分布:表数据在
BE节点上的物理存储位置、副本分布(如每个数据分片的副本所在节点)。 - 任务调度元数据:导入任务、查询任务的执行状态、进度记录等。
- 权限与配置元数据
- 用户与权限:用户账号、角色权限(如某用户对表的
SELECT/INSERT权限)、访问控制列表(ACL)。 - 系统参数:集群的配置参数(如内存限制、查询超时时间)、版本信息等。
2、数据块
Tablet(物理分片顶层)
├─ RowSet 1(导入批次单元)
│ ├─ Segment 1.1(数据逻辑分段)
│ │ ├─ 列1文件
│ │ │ ├─ Data Block 1(逻辑数据分组)
│ │ │ │ ├─ Page 1(物理存储块)
│ │ │ │ └─ Page 2(物理存储块)
│ │ │ └─ Data Block 2(逻辑数据分组)
│ │ ├─ 列2文件
│ │ └─ ...
│ └─ Segment 1.2(数据新版本)
├─ RowSet 2(导入批次单元)
└─ ...
| 组件 | 层级定位 | 数据类型 | 与其他组件的关系 | 核心功能 | 典型应用场景 |
|---|---|---|---|---|---|
Tablet |
物理分片顶层 | 分布式存储单元 | 包含多个 RowSet |
数据分片、副本管理、跨节点迁移 | 分布式查询时定位数据所在节点 |
RowSet |
导入批次中层 | 逻辑导入单元 | 属于某个 Tablet,包含多个 Segment |
记录一次完整导入的数据,管理数据版本(如新旧版本隔离) | 数据导入时生成独立批次,合并时按批次处理 |
Segment |
数据逻辑中层 | 数据组织单元 | 属于某个 RowSet,包含列文件 |
维护列统计信息(最大值 / 最小值 / NULL),用于大范围数据过滤 |
查询时通过统计信息跳过不包含目标数据的 Segment |
Data Block |
列存逻辑底层 | 列数据分组 | 属于列文件,由 Page 组成 |
按列存储的数据逻辑分组,支持压缩和编码,细粒度过滤条件匹配 | 列存查询时定位具体数据范围 |
Page |
物理存储底层 | 磁盘读写单元 | 存储 Data Block 或行数据 |
物理 IO 最小单位,存储实际数据或索引(如 Bloom Filter) |
磁盘读写时的最小数据块,影响 IO 效率 |
Tablet:分布式存储的物理分片单元- 定位:每个分桶文件就是一个数据分片(
Tablet),Tablet是数据划分的最小逻辑单元,也是数据移动、复制等操作的最小物理存储单元3。各个Tablet之间的数据没有交集,并且在物理上是独立存储的。用户可以指定一个或多个维度列以及桶数对数据进行 HASH 分布,从而将数据均匀地分布到不同的桶中,每个桶对应一个Tablet4。在Doris中,表的总Tablet数等于分区数乘以每个分区的桶数2。例如,如果一个表有10个分区,每个分区有16个桶,那么该表就有160个Tablet。 - 结构:每个
Tablet包含元信息(如分区、分桶规则)和若干个RowSet,每个RowSet由多个Segment组成。
- 定位:每个分桶文件就是一个数据分片(
RowSet:RowSet是Doris中数据写入时生成的物理存储单元,- 定位:代表一次完整的数据导入(如通过
BrokerLoad、StreamLoad等方式导入的数据)。每个RowSet由多个Segment组成,每个Segment对应数据的一个版本(例如,同一RowSet内的Segment可能因数据更新而产生新版本)。
- 定位:代表一次完整的数据导入(如通过
Segment:Tablet内的数据逻辑组织单元- 定位:
Tablet内按数据写入顺序或大小划分的逻辑存储单元,每个Segment由多个物理文件组成(如列存的列文件、行存的行数据文件)。- 数据分段存储:每个
Tablet内部按时间、导入批次或数据特性拆分为多个Segment,每个Segment是自包含的逻辑数据块(包含数据、索引、元数据)。 - 与物理存储的解耦:
Segment不直接对应磁盘文件,而是通过逻辑分组管理数据,类似 “文件夹中的子文件夹”,便于数据管理和查询优化。
- 数据分段存储:每个
- 作用:以
Segment为单位维护统计信息(最大值、最小值等),用于查询时过滤无效数据范围。
- 定位:
- 逻辑数据块(
DataBlock):列存中的数据组织单元- 定位:列存模式下,每个列的数据按行分组形成的逻辑块(如默认每
1024行组成一个 Data Block)。 - 作用:列存数据按
DataBlock压缩、编码,查询时可按DataBlock过滤(如通过统计信息判断是否包含目标数据)。
- 定位:列存模式下,每个列的数据按行分组形成的逻辑块(如默认每
Page:物理读写的最小物理单元- 定位:存储引擎中磁盘读写的最小单位(如默认
16KB),DataBlock会被拆分为多个Page存储。 - 作用:每次
IO操作至少读取一个Page,Page级统计信息进一步缩小查询时的IO范围。
- 定位:存储引擎中磁盘读写的最小单位(如默认


