前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

一、Apache Doris 简介

介绍:Apache Doris 是一款基于 MPP (Massively Parallel Processing) 大规模并行处理 架构的高性能、实时分析型数据库。它以高效、简单和统一的特性著称,能够在亚秒级 (小于 1 秒但大于 1 微秒) 的时间内返回海量数据的查询结果Doris 既能支持高并发的点查询场景,也能支持高吞吐的复杂分析场景。

典型场景:基于这些优势,Apache Doris 非常适合用于报表分析、即席查询、统一数仓构建、数据湖联邦查询加速等场景。用户可以基于 Doris 构建大屏看板、用户行为分析、AB 实验平台、日志检索分析、用户画像分析、订单分析等应用。

二、发展历程

Apache Doris 最初是百度广告报表业务的 Palo 项目。2017 年正式对外开源,

20187 月由百度捐赠给 Apache 基金会进行孵化。在 Apache 导师的指导下,由孵化器项目管理委员会成员进行孵化和运营。

20226 月,Apache Doris 成功从 Apache 孵化器毕业,正式成为 Apache 顶级项目(Top-Level ProjectTLP)。

目前,Apache Doris 社区已经聚集了来自不同行业数百家企业的 600 余位贡献者,并且每月活跃贡献者人数超过 120 位。

三、应用现状

Apache Doris 在中国乃至全球范围内拥有广泛的用户群体。截至目前,Apache Doris 已经在全球超过 4000 家中大型企业的生产环境中得到应用。

在中国市值或估值排行前 50 的互联网公司中,有超过 80% 长期使用 Apache Doris,包括百度、美团、小米、京东、字节跳动、阿里巴巴、腾讯、网易、快手、微博等。同时,在金融、消费、电信、工业制造、能源、医疗、政务等传统行业也有着丰富的应用。

在中国,几乎所有的云厂商,如阿里云、华为云、天翼云、腾讯云、百度云、火山引擎等,都在提供托管的 Apache Doris 云服务。

四、使用场景

数据源经过各种数据集成和加工处理后,通常会进入实时数据仓库 Doris 和离线湖仓(如 HiveIcebergHudi),广泛应用于 OLAP 分析场景,Apache Doris 主要应用于以下场景:

1、实时数据分析:

  • 实时报表与实时决策: 为企业内外部提供实时更新的报表和仪表盘,支持自动化流程中的实时决策需求。
  • 交互式探索分析: 提供多维数据分析能力,支持对数据进行快速的商业智能分析和即席查询(Ad Hoc),帮助用户在复杂数据中快速发现洞察。
  • 用户行为与画像分析: 分析用户参与、留存、转化等行为,支持人群洞察和人群圈选等画像分析场景。

2、湖仓融合分析:

  • 湖仓查询加速: 通过高效的查询引擎加速湖仓数据的查询。
  • 多源联邦分析: 支持跨多个数据源的联邦查询,简化架构并消除数据孤岛。
  • 实时数据处理: 结合实时数据流和批量数据的处理能力,满足高并发和低延迟的复杂业务需求。

3、半结构化数据分析:

  • 日志与事件分析: 对分布式系统中的日志和事件数据进行实时或批量分析,帮助定位问题和优化性能。

五、整体架构

Apache Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL。用户可以通过各类客户端工具访问 Apache Doris,并支持与 BI 工具无缝集成。

1、存算一体

Frontend (FE) 主要负责接收用户请求、查询解析和规划、元数据管理以及节点管理,包含 3 个角色。

Backend (BE) 负责物理数据的存储和计算。数据会被切分成数据分片(Shard),在 BE 中以多副本方式存储。

FEBE 进程都可以横向扩展。单个集群可以支持数百台机器和数十 PB 的存储容量。FEBE 进程通过一致性协议来保证服务的高可用性和数据的高可靠性。存算一体架构高度集成,大幅降低了分布式系统的运维成本。

image-20250619155639892

2、存储引擎

在存储引擎方面,Apache Doris 采用列式存储,按列进行数据的编码、压缩和读取,能够实现极高的压缩比,同时减少大量非相关数据的扫描,从而更有效地利用 IOCPU 资源。

1)基本情况

a、索引结构

Apache Doris 也支持多种索引结构,以减少数据的扫描:

  • Sorted Compound Key Index 最多可以指定三个列组成复合排序键。通过该索引,能够有效进行数据裁剪,从而更好地支持高并发的报表场景。
  • Min/Max Index 有效过滤数值类型的等值和范围查询。
  • BloomFilter Index 对高基数列的等值过滤裁剪非常有效。
  • Inverted Index 能够对任意字段实现快速检索。

b、存储模型

在存储模型方面,Apache Doris 支持多种存储模型,针对不同的场景做了针对性的优化:

  • 明细模型(Duplicate Key Model): 适用于事实表的明细数据存储。
  • 主键模型(Unique Key Model): 保证 Key 的唯一性,相同 Key 的数据会被覆盖,从而实现行级别数据更新。
  • 聚合模型(Aggregate Key Model): 相同 KeyValue 列会被合并,通过提前聚合大幅提升性能。

c、其他

Apache Doris 也支持强一致的单表物化视图和异步刷新的多表物化视图。单表物化视图在系统中自动刷新和维护,无需用户手动选择。多表物化视图可以借助集群内的调度或集群外的调度工具定时刷新,从而降低数据建模的复杂性。

2)存储流程

INSERT INTO sales VALUES (1, 100.0);

BE 处理流程

  1. FE Leader 解析 SQL,确定数据应写入的 BE 节点(如根据 Hash 分桶)。
  2. 数据分发:导入任务首先将数据分发到所有相关的 BE 节点。
  3. 并行写入:各个 BE 节点并行处理数据写入操作。
  4. 写入确认:每个 BE 节点在完成数据写入后,会向 FE 发送确认信息。
  5. 多数派判断:FE 统计成功写入的副本数,当达到多数派时,认为导入成功。
  6. 事务提交:FE 提交导入事务,使数据对外可见。
  7. 异步复制:对于未成功写入的副本,系统会在后台异步进行数据复制,以确保最终所有副本的数据一致性。

多数派写入策略是 Doris 在数据可靠性和系统可用性之间的一个平衡。对于有特殊需求的场景,Doris 提供了最小写入副本数等其他选项来进一步提高系统的灵活性。

3、查询引擎

Apache Doris 采用大规模并行处理(MPP)架构,支持节点间和节点内并行执行,以及多个大型表的分布式 Shuffle Join,从而更好地应对复杂查询。

image-20250619182504075

1)查询流程

a、Query(用户发起查询)

  • 节点选择:用户客户端 → FE

    含义:用户通过 MySQL 协议向 Doris 前端( Frontend )发送 SQL查询请求

  • 内部处理

    • 查询首先到达 FrontendQuery Planner 组件
    • 不涉及具体节点选择,是查询流程的起点

b、Send fragment(发送查询片段)

  • 节点选择FrontendBackend
  • 含义Query Coordinator 将优化后的查询计划拆分为多个可并行执行的 Fragment(片段)

c、Fully MPP distributed(完全 MPP 分布式执行)

  • 节点选择BackendBackend

  • 含义:各 BE 节点并行执行分配的 Fragment,并通过网络交换中间数据

    关键点

    • 节点间通过 Shuffle 进行数据重分布(如 Hash ShuffleBroadcast等)

d、Results(返回部分结果)

  • 节点选择BackendFrontend
  • 含义:各 BE 节点将部分计算结果返回给 Frontend
  • 关键点
    • 不是所有 BE 都直接返回给用户,而是先汇总到 Frontend
    • 对于聚合查询,可能包含本地聚合结果

e、Return results(返回最终结果)

  • 节点选择Frontend → 用户客户端
  • 含义:前端将最终结果集返回给用户
  • 关键点:前端 Query Coordinator 组件负责最终汇总

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 客户端发送 SQLFrontend
  • Query Planner 组件:
    • 解析 SQL 生成语法树
    • 检查元数据(orders 表的 region / product_id / amount 字段)
    • 识别分区键(order_date)进行分区剪枝

b、计划生成与分发

  • Query Planner 生成分布式执行计划:
Fragment 1: Scan orders表带日期过滤
Fragment 2: Hash Aggregate region + product_id 分组求和
Fragment 3: Merge Aggregate + TopN排序
  • Query CoordinatorFragment 分发:
  • Fragment 1-1 / 1-2 / 1-3:分配到存储 orders表不同分片的 3BE 节点

  • Fragment 2-1 / 2-2:分配到 2 个计算节点

  • Fragment 3-1:单独一个节点做最终聚合

c、分布式执行阶段

  • BE 节点并行执行

    • Fragment 1-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))
        
    • Fragment 2-x 节点:计算节点

      • 接收来自多个Fragment1-x的数据

      • 按(region, product_id)分组求和

      • 输出部分聚合结果

      • receive_data = shuffle_receive(hash_key)
        local_agg = hash_aggregate(receive_data)  # 本地聚合
        send_to(Fragment3, all_data)
        

d、结果收集

  • Fragment 3-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

image-20250619215038580

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 个桶,那么该表就有 160Tablet

b、存储分片规则可视化

image-20250619220505534

c、Fragment 的角色分工

  • 阶段1:分布式扫描(Fragment 1):负责数据扫描和基础过滤(如日期过滤)

    • 每个 BE 只扫描本地存储的分片(数据本地化)

    • 自动跳过不包含目标日期的分片(分区剪枝)

  • 阶段2:分布式聚合(Fragment 2):负责分布式聚合计算
    • 相同 (region,product_id ) 的数据被 Shuffle 到同一个BE节点
    • 图中 Fragment 2-12-2 并行处理不同哈希桶的数据
  • 阶段3:结果合并(Fragment 3):负责最终结果合并

image-20250619220840544

d、为什么过滤和计算要分开?

1、数据本地化原则(Where过滤)

  • 存储节点执行过滤的优势:

  • 减少网络传输(先过滤再传输)

  • 利用本地存储索引加速过滤

  • 图中 Fragment 1-1 / 1-2 / 1-3 在不同 BE节点并行扫描和过滤

  1. 计算专业化原则(聚合计算)
  • 专用计算节点的优势:
    • 聚合计算需要更多 CPU 资源
    • 避免与 I/O 操作竞争资源
    • 您图中 Fragment 2-1 / 2-2 是专门负责聚合的计算节点

e、汇总职责到底谁来承担

image-20250620091148381

问题1:Query CoordinatorFE)的汇总职责 是什么?

  • 全局结果收集,负责接收所有 BE 节点返回的最终结果片段,并将其合并为完整的查询结果返回给客户端,若查询涉及多个Fragment 3-1 实例(并行执行),FE 会整合这些实例的结果(如合并排序后的 TopN 结果)

问题2:Fragment 3-1BE)的汇总职责 是什么?

  • 中间结果聚合:负责将下层 Fragment(如 Fragment 2-x 的哈希聚合结果)进行跨节点合并Merge Aggregate)和排序(TopN)例如:Fragment 2-1Fragment 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 节点内,但逻辑分层) 是( CoordinatorFE 的核心模块之一)*

image-20250620092319405

问题2:FE 内部任务分配—-> Query Coordinator 协调器是怎么选中的:

答案:FE 收到请求后,会根据 负载均衡 选自身或其他 FECoordinator (也可能直接自己干 )简单说:FE 谁先接到请求、谁负载低、谁元数据全,谁就更可能当查询 CoordinatorLeader/Follower 因元数据强一致,是 “优先候选”,Observer 是 “补充候选

六、组件介绍

1、FE 3 种角色

在生产环境中,可以部署多个 FE 节点以实现容灾备份。每个 FE 节点都会维护完整的元数据副本。FE 节点分为以下三种角色:

  • LeaderFE Master 节点负责元数据的读写。当 Master 节点的元数据发生变更后,会通过 BDB JE 协议同步给 FollowerObserver 节点。

  • FollowerFollower 节点负责读取元数据。当 Master 节点发生故障时,可以选取一个 Follower 节点作为新的 Master 节点。

  • ObserverObserver 节点负责读取元数据,主要目的是增加集群的查询并发能力。Observer 节点不参与集群的选主过程。

一般情况下,每台 FE 节点可以负责 10-20BE 节点的负载操作,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 设计 FollowerObserver 是为了平衡 可用性扩展性

  • Follower 是 “可靠的副本”, 是 Raft 共识的参与者,通过强一致性协议保证元数据与 Leader 实时同步,确保故障时能无缝接管集群,适用于所有对元数据准确性要求高的读取场景。。
  • Observer 是 “高效的扩展”,是 Raft 共识的旁观者,通过牺牲强一致性(允许秒级延迟)换取读能力扩展,适用于对元数据实时性不敏感的分析场景。适合分析型场景(如电商大盘数据统计,允许秒级延迟)。

3)FollowerLeader 的强一致性

解释:通过 Raft 协议的 多数派确认机制 保障一致性:例如 3Follower 中,Leader 需至少收到 2FollowerACK 才提交写入,避免脑裂场景下的数据不一致。少数节点的 “不同意”(如故障、延迟、日志不一致)只是暂时状态,通过日志同步机制最终会被修复。

典型场景:金融交易系统查询订单表,要求实时看到最新创建的表结构,必须连接 LeaderFollower

4)Observer 的扩展性优势

无状态扩展Observer 不参与 Raft 共识,可无限扩展(如 50 个节点),适合海量读请求场景(如每日亿级次报表查询)。

延迟容忍场景:例如电商平台的用户行为分析,允许新创建的分析表在 3 秒后被查询到,可通过 Observer 承载这类请求。

问题1:什么时候可以决定使用 Observer

答案:客户端主动配置 + FE 自动调度 + 业务场景适配 ,三者结合决定是否用 Observer

  • 如果是高并发、非实时的读请求,优先往 Observer 上引;
  • 如果是实时性要求高的,必须走 Leader / Follower

image-20250619184439355

5)Follower 的限制

必须奇数且数量有限

选举与高可用要求:,需满足奇数数量(如1、3、5个)以保证选举的多数决机制

  • 部署 1 个 Follower :仅实现读高可用(无选举容灾能力)。
  • 部署 3 个 Follower:实现读写高可用(Leader 故障时可自动切换)
  • 性能瓶颈:所有 Follower 需实时同步 Leader 的元数据变更(如 DDL 、导入事务),Follower 越多,日志复制延迟风险越高,可能拖慢集群响应速度
  • 选举复杂度Follower 数量过多会降低选举效率,增加故障恢复时间
  • 运维成本:奇数数量的 Follower 需跨故障域部署(如不同机架),无限扩展会大幅提升部署和监控成本

  • 建议数量
    • 官方推荐生产环境部署 3Follower (满足高可用)和 1 - 3Observer (扩展读能力),而非无限扩展Follower
    • 在线业务3 Follower + N Observer(保障 HA 和读扩展)
    • 离线业务1 Follower + N Observer(节省资源)

6)建表流程

CREATE TABLE sales (
  id INT,
  amount DOUBLE
) DISTRIBUTED BY HASH(id) BUCKETS 10;

FE 处理流程

  1. 客户端发送 SQLFE Leader
  2. LeaderCREATE TABLE 转为元数据日志,写入本地 Raft 日志。
  3. Leader 通过 Raft 复制日志到所有 Follower,等待多数派(如 3 节点中的 2 个)确认。
  4. 多数派确认后,Leader 提交日志,更新内存中的表结构,并返回成功给客户端。
  5. 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、业务数据可按需调整

  • 强一致场景(如金融交易):写 ALLQUORUM 副本,确保数据不丢失,但牺牲写入性能。
  • 最终一致场景(如用户行为日志):异步复制,写入性能高,但可能在故障时丢失少量未同步数据(主副本故障会丢)。

4)BE:读取模式区别

  • QUORUM(多数派读写):当使用 QUORUM 模式时,Doris 在读操作时会从多个副本中读取,并确保大多数副本的数据一致才返回结果。写操作则要求数据被复制到大多数副本上。
    • 优点:提供了较好的一致性和可用性保证。即使部分副本不可用,只要大多数副本正常工作,系统仍能提供服务。

    • 缺点:相比 ASYNC 模式,可能会稍微降低一些性能,因为它需要等待多个副本响应。

  • ALL(全量读写):ALL 模式下,所有的读写操作都需要涉及到的所有副本都成功才能完成。这意味着对于读操作,必须从所有副本获取数据并确认它们是一致的;对于写操作,则需要确保数据被成功写入所有副本。

    • 优点:提供了最强的一致性保证,因为所有副本的数据都是同步更新的。

    • 缺点:如果有一个副本出现问题或延迟,整个操作将会受到影响,可能导致较高的延迟甚至失败。因此,这种模式通常用于对一致性要求极高的场景。

  • ASYNC(异步读写):使用 ASYNC 模式 (默认)时,读操作可以从任意一个副本执行,而不需要检查其他副本的状态。写操作则是异步地将数据复制到其他副本上。
  • 优点
    • 高性能:由于不需要等待所有副本的数据同步完成即可进行读取,因此能够提供较低的延迟和较高的吞吐量。
    • 最终一致性:在写入后立即执行的读取可能会遇到旧数据,但随着时间推移,所有副本将最终达到一致状态。
  • 缺点:牺牲了一定程度的一致性,因为在写入后立即进行读取可能不会得到最新的数据,直到所有副本都被更新为止。适用于那些可以容忍一定程度数据不一致的应用场景。

六、Apache Doris 的核心特性

高可用: Apache Doris 的元数据和数据均采用多副本存储,并通过 Quorum 协议同步数据日志。当大多数副本完成写入后,即认为数据写入成功,从而确保即使少数节点发生故障,集群仍能保持可用性。 Apache Doris 支持同城和异地容灾,能够实现双集群主备模式。当部分节点发生异常时,集群可以自动隔离故障节点,避免影响整体集群的可用性。

高兼容: Apache Doris 高度兼容 MySQL 协议,支持标准 SQL语法,涵盖绝大部分 MySQLHive 函数。通过这种高兼容性,用户可以无缝迁移和集成现有的应用和工具。Apache Doris 支持 MySQL 生态,用户可以通过 MySQL 客户端工具连接 Doris,使得操作和维护更加便捷。同时,可以使用 MySQL 协议对 BI 报表工具与数据传输工具进行兼容适配,确保数据分析和数据传输过程中的高效性和稳定性。

实时数仓: 基于 Apache Doris 可以构建实时数据仓库服务。Apache Doris 提供了秒级数据入库能力,上游在线联机事务库中的增量变更可以秒级捕获到 Doris 中。依靠向量化引擎、MPP 架构及 Pipeline 执行引擎等加速手段,可以提供亚秒级数据查询能力,从而构建高性能、低延迟的实时数仓平台。

湖仓一体: Apache Doris 可以基于外部数据源(如数据湖或关系型数据库)构建湖仓一体架构,从而解决数据在数据湖和数据仓库之间无缝集成和自由流动的问题(统一计算层 + 多源存储适配 + 智能数据路由 三大核心技术,实现湖仓间的数据无缝集成与自由流动。以下是具体实现方式:),帮助用户直接利用数据仓库的能力来解决数据湖中的数据分析问题,同时充分利用数据湖的数据管理能力来提升数据的价值。

灵活建模:Apache Doris 提供多种建模方式,如宽表模型、预聚合模型、星型/雪花模型等。数据导入时,可以通过 FlinkSpark 等计算引擎将数据打平成宽表写入到 Doris 中,也可以将数据直接导入到 Doris 中,通过视图、物化视图或实时多表关联等方式进行数据的建模操作。

七、FAQ

1、为什么不能直接替换 MySQL

1)核心优势场景

  • 海量数据分析:10PB 级存储 + 亚秒级查询(聚合 / OLAP 场景),适合数据仓库、BI 报表、实时分析。
  • MySQL 协议兼容:无缝对接现有 MySQL 生态工具(如 Navicat、Sqlyog),降低迁移成本。
  • 极简架构:无复杂组件依赖(对比 Hadoop 生态),运维成本低,适合快速迭代的业务。

2)不可忽视的边界

  • 事务支持有限:仅支持单表主键唯一性约束,不支持跨表事务(对比 MySQL InnoDB)。
  • 非结构化数据处理弱:无法直接处理文档、图片等非结构化数据(需预处理)。
  • 实时写入性能瓶颈:高并发小批量写入(如每秒 10 万 + 单条记录)时效率低于专用实时系统(存储原因导致)。
维度 MySQL(OLTP) Apache Doris(OLAP)
数据模型 行存为主,支持复杂事务和索引 列存为主,面向分析场景优化
写入模式 支持实时增删改(ACID 保障) 批量导入为主(支持分区级更新)
查询场景 低延迟单条 / 小批量数据查询 大规模聚合、多维度分析查询
典型场景 订单系统、用户中心等核心业务 订单统计报表、用户行为分析

2、和 mysql 正确协同方式是什么?

1、正确的协同方式:MySQL 处理实时交易,Doris 负责历史数据聚合分析,通过中间件同步数据。

业务系统(MySQL) → 数据同步(Canal/MaxCompute) → Doris(分析层)

2、读写分离优化:高频查询(如最近 7 天数据)仍由 MySQL 承担,历史数据(>30 天)迁移至 Doris 降低 MySQL 负载。

3、DorisES / ``HBase`

1)对比 ElasticsearchES

  • 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:列族设计支持动态添加列(适合快速迭代的业务)。
  • DorisHBase 的协同

    • HBase 存储原始数据,Doris 作为分析层:
    设备数据 → HBase(实时写入) → 定期同步至Doris(离线分析)
    
    • HBase + Doris 联合查询:通过外表功能(Doris 1.2+)直接查询 HBase 数据,避免数据冗余。

电商平台架构

Doris 的角色:承接 Flink 计算结果,提供多维度分析(如 “按地域 + 时间 + 商品类目统计 GMV”)。

[业务层] MySQL(订单交易) + Redis(缓存)
[实时层] Kafka(数据流) + Flink(实时计算) + ES(商品搜索)
[分析层] Doris(用户行为分析、订单统计) + Hive(离线数仓)
[存储层] HBase(用户画像标签) + 对象存储(图片/视频)

附录

1、元数据

元数据是 “关于数据的数据”,它不直接存储业务数据,而是记录数据的 “属性信息”,类似于图书的目录、作者、分类等描述性内容。在 Doris 中,元数据由 FEFrontend)节点集中管理,是整个集群运行的 “大脑中枢”。

  1. 数据结构元数据
  • 表与字段定义:记录表的名称、字段类型(INTSTRING 等)、字段注释、主键约束等。
  • 分区与分桶信息:例如表按时间字段(date)分区,或按哈希值分桶存储,用于优化查询性能。
  • 视图与函数定义:用户创建的视图逻辑、自定义函数(UDF)的元数据信息。
  1. 集群运行元数据
  • 节点状态:各 FEBEBackend)节点的在线状态、IP 地址、资源占用情况。
  • 数据分布:表数据在 BE 节点上的物理存储位置、副本分布(如每个数据分片的副本所在节点)。
  • 任务调度元数据:导入任务、查询任务的执行状态、进度记录等。
  1. 权限与配置元数据
  • 用户与权限:用户账号、角色权限(如某用户对表的 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 效率
  1. Tablet:分布式存储的物理分片单元
    • 定位:每个分桶文件就是一个数据分片(Tablet),Tablet 是数据划分的最小逻辑单元,也是数据移动、复制等操作的最小物理存储单元 3。各个 Tablet 之间的数据没有交集,并且在物理上是独立存储的。用户可以指定一个或多个维度列以及桶数对数据进行 HASH 分布,从而将数据均匀地分布到不同的桶中,每个桶对应一个 Tablet4。在 Doris 中,表的总 Tablet 数等于分区数乘以每个分区的桶数 2。例如,如果一个表有 10 个分区,每个分区有 16 个桶,那么该表就有 160Tablet
    • 结构:每个 Tablet 包含元信息(如分区、分桶规则)和若干个 RowSet,每个 RowSet 由多个 Segment 组成。
  2. RowSetRowSetDoris 中数据写入时生成的物理存储单元,
    • 定位:代表一次完整的数据导入(如通过 Broker LoadStream Load 等方式导入的数据)。每个 RowSet 由多个 Segment 组成,每个 Segment 对应数据的一个版本(例如,同一 RowSet 内的 Segment 可能因数据更新而产生新版本)。
  3. SegmentTablet 内的数据逻辑组织单元
    • 定位Tablet 内按数据写入顺序或大小划分的逻辑存储单元,每个 Segment 由多个物理文件组成(如列存的列文件、行存的行数据文件)。
      • 数据分段存储:每个 Tablet 内部按时间、导入批次或数据特性拆分为多个 Segment,每个 Segment自包含的逻辑数据块(包含数据、索引、元数据)。
      • 与物理存储的解耦Segment 不直接对应磁盘文件,而是通过逻辑分组管理数据,类似 “文件夹中的子文件夹”,便于数据管理和查询优化。
    • 作用:以 Segment 为单位维护统计信息(最大值、最小值等),用于查询时过滤无效数据范围。
  4. 逻辑数据块(Data Block):列存中的数据组织单元
    • 定位:列存模式下,每个列的数据按行分组形成的逻辑块(如默认每 1024 行组成一个 Data Block)。
    • 作用:列存数据按 Data Block 压缩、编码,查询时可按 Data Block 过滤(如通过统计信息判断是否包含目标数据)。
  5. Page:物理读写的最小物理单元
    • 定位:存储引擎中磁盘读写的最小单位(如默认 16KB),Data Block 会被拆分为多个 Page 存储。
    • 作用:每次 IO 操作至少读取一个 PagePage 级统计信息进一步缩小查询时的 IO 范围。

ContactAuthor