Doris 高性能实时分析型数据库
概述
Apache Doris 是一款基于 MPP 架构的高性能、实时分析型数据库,以高效、简单、统一著称:在亚秒级时间内返回海量数据查询结果,一套系统同时支持高并发点查询和高吞吐复杂分析,主要解决大量数据上的聚合、Join、报表、多维分析、日志分析、实时数仓等问题。
Doris 可以直接支持 MySQL 协议和 SQL 语法,但是底层并不是 MySQL,而是面向 OLAP 重新设计的 列式存储 + 向量化执行 + MPP 分布式计算引擎。
与 MySQL 相比,MySQL 更适合 OLTP 事务型业务数据库,Doris 更适合 OLAP 实时分析型数据库。
Doris 应用场景:实时报表与仪表盘、用户行为分析、日志检索分析、统一数仓构建、数据湖联邦查询加速等
架构
Doris 官方有两种部署架构:
存算一体架构
- FE + BE 经典架构,数据存储与计算融合。
- 性能优先、运维资源有限、规模可控。
存算分离架构:
元数据层、计算层、存储层三层分离。
云原生、弹性伸缩、多团队共享数据
存算一体架构
存算一体架构是 Apache Doris 的经典部署模式,计算和存储位于每个节点上,以实现最大的本地 I/O 和最低的查询延迟,由 Frontend(FE) 和 Backend(BE) 两类进程组成。
Frontend(FE):接收请求、查询解析、元数据管理、节点管理,是 Apache Doris 的入口节点,承担协调和控制职能。生产环境部署多个 FE 节点实现高可用,FE 节点分为 Master、Follower、Observer 三种角色。
Backend(BE):数据存储、查询执行(多副本存储),计算和存储节点,数据直接存储在 BE 的本地磁盘。
存算分离架构
从 3.0 版本引入,计算层与存储层完全分离,独立扩展存储容量和计算资源。与存算一体架构的不同之处在于:
计算层:在存算分离架构中,FE 节点依然保留,承担用户请求接入和查询解析职责。同时新增了 Meta Service 专门负责数据层面的元数据管理。
存储层:BE 不再负责持久化存储,主要负责计算,本地磁盘只是 Cache,不再保存持久数据,真正数据存放在 Storage Layer。
选型建议
业务规模可控、追求简单运维 -> 存算一体
需要弹性扩缩容 -> 存算分离
工作原理
- FE 解析 SQL 并生成逻辑执行计划
- 计划拆分为多个 Fragment(逻辑执行单元)
- 每个 Fragment 实例化一个或多个 Instance,分发到多个 BE 节点并行执行
- 不同 Instance 之间通过 Exchange 算子进行网络数据交互
- 各节点执行完成后,结果在 FE 汇总
存储引擎
Apache Doris 采用列式存储作为其核心存储引擎,具有 I/O 效率高、压缩率高、向量化友好的优势。这是它能胜任海量数据在线分析处理(OLAP)场景的关键技术基石。
列式存储与传统的行式存储(如MySQL)在数据组织方式上有着根本不同:
行式存储:将同一行的所有数据连续存放在一起。比如一条用户记录,其ID、姓名、年龄等所有字段是作为一个整体存储的。
列式存储:将同一列的所有数据集中存放在一起。比如所有用户的ID存放在一个连续区域,所有用户的姓名存放在另一个连续区域。
1 | 行式存储(一行连续存放): |
数据模型
在 Doris 中建表时必须指定表模型(Table Model),它决定了数据的存储、去重、聚合与更新方式。Doris 提供三种表模型:明细模型(Duplicate Key)、主键模型(Unique Key)和聚合模型(Aggregate Key),分别覆盖原始数据保留、按主键更新、预聚合分析三类典型场景。表模型在建表后不可修改,因此选型至关重要。
| 模型 | 说明 | 适用场景 |
|---|---|---|
| 明细模型(Duplicate Key) | 保留所有原始数据,相同主键的多条记录全部保留 | 事实表明细存储、日志分析 |
| 聚合模型(Aggregate Key) | 相同主键的数据按聚合函数合并(如 SUM、MAX、MIN) | 指标统计、报表预聚合、流量统计 |
| 主键模型(Unique Key) | 主键唯一,相同主键的记录会覆盖(支持行级更新) | 实时维表、订单状态、用户画像 |
示例:
假设有以下原始数据(主键为 user_id):
| user_id | visit_date | pv |
|---|---|---|
| 1 | 2024-01-01 | 5 |
| 1 | 2024-01-01 | 3 |
| 2 | 2024-01-01 | 10 |
- 明细模型:保留所有 3 条记录
- 聚合模型(按 SUM 聚合):相同主键的
pv合并 → user_id=1 的 pv=8,user_id=2 的 pv=10 - 主键模型:相同主键的记录按时间戳覆盖,最终只保留最新的一条(如
pv=3覆盖pv=5)
高可用机制
多副本与 Quorum 协议
- 每个 Tablet 默认 3 副本存储
- 写入需多数派(如 2 副本)确认成功
- 部分节点故障不丢数据,集群仍可服务
故障自动隔离
- 检测节点心跳超时或副本损坏
- 标记节点不可用,停止分发任务
- 从健康副本自动补齐缺失副本
- 恢复后自动同步增量数据
FE 高可用
Paxos 类共识协议保证元数据一致性。Master 故障时 Follower 自动选举新 Master,对用户透明。
环境准备
| Item | Version |
|---|---|
| Ubuntu | 22.04.5 |
| Doris | 4.1.3 |
| Java | 17 |
| 节点 | IP |
|---|---|
| u68 | 192.168.2.68 |
| u69 | 192.168.2.69 |
| u71 | 192.168.2.71 |
FE:参与选举,Master 宕机时接替,建议 ≥ 3 个。
BE:保证 3 副本可靠存储,建议≥ 3 个。
这里我们在三个节点上都安装 FE + BE。
安装前准备
CPU 检查
Doris 利用 AVX2 向量化能力加速查询,建议选择支持 AVX2 指令集的机器。
1 | cat /proc/cpuinfo | grep avx2 |
若有输出,则表示支持 AVX2。若不支持,可使用 no AVX2 的 Doris 安装包。
swap 关闭
1 | swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab |
关闭透明大页
关闭 THP(Transparent Huge Pages)可减少内存碎片,保证 Doris 稳定使用内存。
1 | echo madvise > /sys/kernel/mm/transparent_hugepage/enabled |
增大虚拟内存区域
1 | cat >> /etc/sysctl.conf << EOF |
禁用 CPU 省电模式
1 | echo 'performance' | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor |
网络连接溢出时重置
启用 tcp_abort_on_overflow 可在连接溢出时立即中断,避免高负载下连接长时间挂起。
1 | cat >> /etc/sysctl.conf << EOF |
防火墙
关闭防火墙或者开放对应端口。
1 | ufw disable |
端口列表:
| 实例 | 端口名称 | 默认端口 | 通信方向 | 说明 |
|---|---|---|---|---|
| BE | be_port | 9060 | FE → BE | Thrift Server,接收 FE 请求 |
| BE | webserver_port | 8040 | BE ↔ BE | HTTP Server |
| BE | heartbeat_service_port | 9050 | FE → BE | 心跳服务(Thrift) |
| BE | brpc_port | 8060 | FE ↔ BE,BE ↔ BE | BRPC 通信 |
| FE | http_port | 8030 | FE ↔ FE,Client ↔ FE | HTTP Server |
| FE | rpc_port | 9020 | BE → FE,FE ↔ FE | Thrift Server,各 FE 需一致 |
| FE | query_port | 9030 | Client ↔ FE | MySQL Server |
| FE | edit_log_port | 9010 | FE ↔ FE | bdbje 通信 |
增大文件句柄数
Doris 依赖大量文件管理表数据,需调高文件句柄限制。
1 | vi /etc/security/limits.conf |
ntp 时间同步
保证集群所有机器时钟同步,元数据时间精度需 < 5000ms。
1 | ntpdate ntp.aliyun.com |
Java 环境
参考此文档说明,Doris 所有进程依赖 Java,其中 Doris 3.0 及之后的版本建议使用 Java 17 版本。
如果主机上已安装其他版本的 JDK,不用担心,一台主机可以安装多个版本,直接安装即可。
其中 Ubuntu 安装如下:
1 | apt install -y openjdk-17-jdk-headless |
配置环境变量:
1 | vi ~/.bashrc |
验证:
1 | java -version |
下载软件包
可以在官方网站获取软件包,这里根据前面 CPU 检查的结果,如果 CPU 支持 AVX2,就下载 avx2 的包。
1 | mkdir /opt/package && cd /opt/package |
存算一体集群部署
FE 节点部署
- 创建元数据路径(可选)
默认是在 fe/doris-meta路径下,生产环境建议分离 doris-meta 元数据路径,使用单独的 SSD 硬盘;开发和测试环境可以使用默认配置。
1 | cd /opt/apache-doris/fe |
1 | mkdir -p <doris_meta_created> |
- 在所有节点上,编辑
fe.conf配置文件
1 | vi conf/fe.conf |
1 | ## 指定参数 -Xmx、-Xms,调整 Java Heap,生产环境建议 16G 以上 |
- 在第一个节点(u68),启动 FE Master 节点
1 | bin/start_fe.sh --daemon |
- 检查 FE 启动状态
可以使用 MySQL 命令行工具连入到 Doris 数据库中,并使用 MySQL 的语法。
1 | mysql -uroot -P9030 -h192.168.2.68 |
1 | show frontends; |
Alive 为 true 表示节点存活;
Join 为 true 表示节点加入到集群中,但不代表当前还在集群内(可能已失联);
IsMaster 为 true 表示当前节点为 Master 节点。
- 添加 FE Follower 节点
通过 MySQL 命令行工具,将另外两个节点(u69、u71)注册为 FE Follower 节点:
1 | ALTER SYSTEM ADD FOLLOWER "192.168.2.69:9010"; |
- 接着启动 u69、u71 的 FE Follower 节点。
1 | bin/start_fe.sh --helper 192.168.2.68:9010 --daemon |
这里的 –helper 要填写集群中任意存活的 FE 节点的 IP,这里可以填写 u68 的 IP,该参数仅在第一次启动 FE 时需要,之后重启无需指定。
- 检查 FE 所有节点状态
1 | show frontends; |
同样检查 Alive、Join、IsMaster参数,其中只有 u68 的 IsMaster 为 true。
BE 节点部署
- 创建数据目录
数据目录默认放在 be/storage 路径下,如果有多块高性能磁盘,BE 支持数据分布在多盘上以更好的利用多块硬盘的 I/O 能力。这里假设有两个磁盘,并挂载在 be/storage-1 和 be/storage-2 路径下。
1 | cd /opt/apache-doris/be |
1 | mkdir -p storage-1 storage-2 |
- 在所有节点上,编辑
be.conf配置文件
1 | vi conf/be.conf |
1 | ## 指定数据目录 |
- 先在 FE 中,注册所有 BE 节点
1 | mysql -uroot -P9030 -h192.168.2.68 |
1 | ALTER SYSTEM ADD BACKEND "192.168.2.68:9050"; |
- 接着所有节点,逐台启动 BE 进程
1 | bin/start_be.sh --daemon |
- 查看 BE 启动状态
1 | mysql -uroot -P9030 -h192.168.2.68 |
1 | show backends; |
live 为 true 表示节点存活
TabletNum 表示该节点上的分片数量,新加入的节点会进行数据均衡,TabletNum 逐渐趋于平均。
修改 Doris 密码
默认 root 用户的密码为空,为了提高安全性,可以为 root 设置密码。
1 | select user(); |
存算分离集群部署
FoundationDB 部署
官方的软件包,默认自带了 FoundationDB 的安装脚本,可以直接配置和使用。
- 配置
fdb_vars.sh脚本
1 | cd /opt/apache-doris/tools/fdb |
1 | # 以下参数必须指定 |
1 | # 可选参数 |
- 部署 FDB 集群
由于 Doris 软件包里默认不带 FDB 相关的包,在部署过程中如果检测到本地没有 FDB 的包会自动从外网拉取。如果是离线环境,可以提前将这个包拉下来。
仅离线环境需要手动拉取 FDB 包:
1 | ## FDB_VERSION 具体版本可以在 fdb_vars.sh 配置文件里获取 |
接着执行该命令部署 FDB 集群
1 | ./fdb_ctl.sh deploy |
- 所有节点逐台启动 FDB 集群
1 | ./fdb_ctl.sh start |
- 检查 FDB 集群
1 | pkgs/7.3.69/fdbcli -C /opt/apache-doris/fdbhome/conf/fdb.cluster --exec "status" |
确认在 Cluster - Machines 是 3 即可。
Meta Service 部署
- 在所有节点上,编辑
doris_cloud.conf配置文件
1 | cd /opt/apache-doris/ms |
1 | ## Meta Service 的监听端口,默认为 5000 |
- 启动 ms
1 | export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 |
启动脚本返回值为 0 表示启动成功,否则启动失败。启动成功同时标准输出的最后一行文本信息为 “doris_cloud start successfully”。
生产环境中请确保至少有 3 个 Meta Service 节点。
关于数据回收功能(Recycler),Meta Service 本身具备了元数据管理和回收功能,这两个功能也可以分开部署,小规模集群不用单独部署 Recycler,具体可查看官方文档,这里不在赘述。
FE 节点部署
- 所有节点配置
fe.conf
1 | cd /opt/apache-doris/fe |
1 | ## 指定参数 -Xmx、-Xms,调整 Java Heap,生产环境建议 16G 以上 |
- 在第一个节点(u68),启动 FE Master 节点
1 | bin/start_fe.sh --daemon |
- 检查 FE 启动状态
可以使用 MySQL 命令行工具连入到 Doris 数据库中,并使用 MySQL 的语法。
1 | mysql -uroot -P9030 -h192.168.2.68 |
1 | show frontends; |
第一个 FE 会自动初始化集群并成为 Master,同时以 FOLLOWER 角色工作。
- 注册 FE Follower/Observer 节点
还是需要先通过 sql 命令添加进来
1 | mysql -uroot -P9030 -h192.168.2.68 |
1 | ALTER SYSTEM ADD FOLLOWER "192.168.2.69:9010"; |
在另外两台(u69、u71)启动 fe 进程
1 | bin/start_fe.sh --helper 192.168.2.68:9010 --daemon |
- 检查 FE 所有节点状态
1 | show frontends; |
能看到三个节点都是 FOLLOWER 角色,Alive 都为 true,并且 u68 是 Master。
官方建议生产 FE Follower 数量保持奇数,一般三个 Follower 即可。Observer 可以是任意数量。
BE 节点部署
- 所有节点配置
be.conf
1 | cd /opt/apache-doris/be |
1 | ## 指定参数 -Xmx,调整 Java Heap,生产环境建议 2G 以上 |
- 接着启动 BE 进程
1 | bin/start_be.sh --daemon |
- 创建 Compute Group,并将三个 BE 加入同一个 Compute Group
1 | mysql -uroot -P9030 -h192.168.2.68 |
1 | ALTER SYSTEM ADD BACKEND "192.168.2.68:9050" |
- 查看 BE 启动状态
1 | mysql -uroot -P9030 -h192.168.2.68 |
1 | show backends; |
查看 Compute Group 可以看到有 3 个节点。
安装 S3 或 HDFS 服务(可选)
Doris 的存算分离模式依赖于 S3 或 HDFS 服务来存储数据,如果已有相关存储服务,直接使用即可。这里可以参考我另一篇关于 [Hadoop3.5.0 集群搭建](https://www.zerchin.com/2026/08/29/hadoop/Hadoop3.5.0 集群搭建/) 文档。
或者官方也提供简单的 MinIO的部署教程:
在 MinIO 的下载页面选择合适的版本以及操作系统,下载对应的 Server 以及 Client 的二进制包或安装包。
启动 MinIO Server
1
2
3
4export MINIO_REGION_NAME=us-east-1
export MINIO_ROOT_USER=minio # 在较老版本中,该配置为 MINIO_ACCESS_KEY=minio
export MINIO_ROOT_PASSWORD=minioadmin # 在较老版本中,该配置为 MINIO_SECRET_KEY=minioadmin
nohup ./minio server /mnt/data 2>&1 &配置 MinIO Client
1
2# 如果你使用的是安装包安装的客户端,那么客户端名为 mcli,直接下载客户端二进制包,则其名为 mc
./mc config host add myminio http://127.0.0.1:9000 minio minioadmin创建一个桶
1
./mc mb myminio/doris
验证是否正常工作
1
2
3
4# 上传一个文件
./mc mv test_file myminio/doris
# 查看这个文件
./mc ls myminio/doris
添加 Storage Vault
Storage Vault 是 Doris 存算分离架构中的重要组件。它们代表了存储数据的共享存储层。
可以使用 HDFS 或兼容 S3 的对象存储创建一个或多个 Storage Vault。可以将一个 Storage Vault 设置为默认 Storage Vault,系统表和未指定 Storage Vault 的表都将存储在这个默认 Storage Vault 中。默认 Storage Vault 不能被删除。
可以在这里找到 S3 Vault 和 HDFS Vault 的参数。这里我们以 HDFS 为例。
- 进入 HDFS,确认当前的用户和组是什么
1 | hdfs dfs -mkdir /test |
例如可以看到:
1 | drwxr-xr-x - hadoop supergroup 0 2026-08-31 10:30 /test |
说明是 user:group 是 hadoop 和 supergroup
- 创建 HDFS Storage Vault
1 | CREATE STORAGE VAULT IF NOT EXISTS hdfs_vault |
参数说明:
| 参数 | 作用 |
|---|---|
| type | 对接的 Storage Vault 类型,这里填写的 hdfs |
| fs.defaultFS | HDFS 地址 |
| path_prefix | Doris 数据路径前缀 |
| hadoop.username | 访问 HDFS 的用户 |
这里如果 hdfs 对接的时候用户名写错,在创建数据库和表时不会报错,但是会在写入数据的时候提示没权限。
1 | mysql> insert into mytable values |
可以使用这条命令修改成正确的用户名:
1 | ALTER STORAGE VAULT hdfs_vault |
- 设置默认 Vault
1 | SET hdfs_vault AS DEFAULT STORAGE VAULT; |
- 检查 Storage Vault状态
1 | SHOW STORAGE VAULTS; |
Docker 快速启动
官方有个一键启动的脚本,会部署一个单点的 FE + BE 双容器的 docker compose 应用,但是这两个镜像里默认 HEAP 的内存比较大,如果内存比较小的虚拟机会无法启动容器。
但 Doris 还提供了个 all-in-one 镜像,默认 FE_HEAP=2048m、BE_HEAP=1024m,虚拟机大于 2G 即可启动并验证功能。
1 | docker run -d --name doris -p 9030:9030 -p 8030:8030 -p 8040:8040 apache/doris:all-in-one-4.1.3 |
功能验证
- 创建数据库
1 | create database demo; |
- 创建表
1 | create table mytable |
- 导入测试数据
1 | insert into mytable values |
- 查询
1 | select * from demo.mytable; |
这里如果是存算分离集群,那么就可以在对接的存储里看到数据,例如 HDFS
1 | # hdfs dfs -ls / |
常用操作
查看版本
1 | SELECT VERSION(); |
查看FE/BE组件状态
1 | SHOW FRONTENDS; |
查看 Compute Group
1 | SHOW COMPUTE GROUPS; |
查看 Storage Vault
1 | SHOW STORAGE VAULTS; |
Doris PROC 系统
1 | SHOW PROC "/"; |
创建 DUPLICATE KEY 表
1 | CREATE TABLE user_behavior ( |
创建 Unique Key 表
1 | CREATE TABLE users ( |
创建 Aggregate Key 表
1 | CREATE TABLE sales ( |
查看表数据量
1 | SHOW DATA; |
查看表的 Tablet
1 | SHOW TABLETS FROM ecommerce_demo.users; |
查看 Replica 状态
1 | SHOW REPLICA STATUS FROM users; |
用户
1 | SELECT User, Host |
使用 Stream Load 方式导入数据
接口:http://FE_IP:8030/api/{db}/{table}/_stream_load
假设有个数据库和表:
1 | CREATE DATABASE testdb; |
本地有个 test.csv 文件:
1 | 1,Emily,25 |
导入数据:
1 | curl --location-trusted -u <doris_user>:<doris_password> \ |
读取 HDFS 的 CSV 文件
假设 HDFS 在 /test 路径下有个 test.csv 文件
1 | hdfs dfs -mkdir /test |
在 Doris 中读取该文件
1 | select * from hdfs( |
参考链接: