第 05 关 · ★★

五分钟上手:部署到第一次查询

部署、连接、建表、导入、查询:搭出一个可复现的 Doris 实验环境。

已点亮 · 最佳 分

Quick Start:从零部署、连接、建表、导入与第一次查询

把前四天的概念落到真实环境,搭出一套能反复使用的实验底座

Docker 体验FE/BE 部署Stream Load排障方法
1 / 28

Day 5|Quick Start:从零部署、连接、建表、导入与第一次查询

前四天,我们依次建立了数据系统版图,认识了 Doris 的定位,理解了 FE、BE、MPP、列存、向量化与 Pipeline,也讨论了存算一体、存算分离和版本路线。

今天开始把这些概念落到真实环境里。学习完成的标志很明确:你能够启动一个 Doris 集群,确认 FE 与 BE 真正加入集群,创建第一张表,完成两种写入,执行查询,并且知道出错后应该先看哪里。

Day 5 Quick Start 学习总览
Day 5 Quick Start 学习总览

本日学习目标

完成今天的学习后,你应当能够:

  1. 区分五分钟 Docker 体验与本地完整部署的用途;
  2. 按照 Doris 4.x 当前要求检查 Linux、JDK、文件句柄、内存映射、网络与磁盘;
  3. 配置并启动 FE、BE,理解 priority_networks、元数据目录和数据目录的作用;
  4. 通过 MySQL 协议连接 Doris,确认 FE 的 Join、Alive、Master 状态以及 BE 的心跳状态;
  5. 创建数据库和第一张 Duplicate Key 表,使用 INSERT 写入数据;
  6. 使用 Stream Load 导入 CSV,并正确读取同步返回结果;
  7. 根据日志、端口、节点状态和错误返回定位常见问题;
  8. 整理一个能够启动、验证、播种、停止和重置的实验仓库。

一、今天真正要搭建的,是一套“可重复实验能力”

初次接触数据库时,很多人把“部署成功”理解为进程已经启动。这个判断过于宽松。FE 进程存在,可能仍在反复报错;BE 进程存在,可能没有向 FE 正常发送心跳;MySQL Client 能连上 FE,也无法证明表的副本可以写入;一条查询返回结果,还需要继续确认导入行数和聚合口径。

今天使用四层判据验收环境:

层次 验证对象 成功标志
主机层 操作系统、JDK、磁盘、端口、权限 环境检查通过,目录可写,端口无冲突
进程层 FE、BE 进程与日志 进程稳定运行,启动日志无持续错误
集群层 FE 元数据状态、BE 心跳 FE Join=trueAlive=true;BE Alive=true
数据层 建表、写入、查询与对账 导入成功,行数一致,查询结果符合预期

这四层会贯穿后续 25 天。学习数据模型时需要反复重建表,学习分区分桶时需要观察 Tablet,学习导入时需要制造失败任务,学习优化时需要采集执行计划和 Profile。稳定的实验底座能够降低每一天的准备成本,让注意力集中在 Doris 本身。

1.1 学习环境和生产环境承担不同目标

学习环境追求以下能力:

  • 启动速度快;
  • 资源占用可控;
  • 能够随时清空和重置;
  • 配置与数据种子固定;
  • 每个人都能得到相同结果;
  • 失败后可以快速重来。

生产环境关注高可用、数据可靠、容量增长、故障恢复、权限、安全、监控、备份和变更治理。单机环境可以证明功能链路成立,无法证明生产稳定性。两者共用 SQL 与核心组件,验收标准和拓扑规模有明显差异。

学习环境与生产环境对比
学习环境与生产环境对比

本篇采用一个 FE、一个 BE 的存算一体拓扑。所有进程可以放在同一台 Linux 主机上,表的副本数设置为 1。这个拓扑仅服务于学习、功能验证和小规模 POC。常见生产起点是三个参与选举的 FE Follower,加上至少三个 BE,并按照业务需要配置多副本、负载入口、监控、备份和安全策略。


二、两条启动路径:先快速获得反馈,再完整理解组件

Apache Doris 4.x 官方 Quick Start 提供两条路线:

  • Docker 快速启动:几分钟内得到一个完整可用集群,适合第一次体验;
  • 本地完整部署:分别配置 FE 和 BE,适合理解生产部署的基本结构。

Docker 与本地完整部署两条路径
Docker 与本地完整部署两条路径

建议按顺序完成两条路线。Docker 路线让你尽快看到查询结果,建立正反馈;本地二进制路线帮助你掌握目录、配置、端口、日志、注册和心跳。后续运维排障需要依赖第二条路线形成的知识。

2.1 Docker 路线适合解决什么问题

Docker 路线适合回答三个问题:

  1. 本机是否能够运行 Doris;
  2. MySQL Client 是否能够连接;
  3. Doris SQL、建表和查询是否能够正常执行。

它不适合直接推导生产结论。官方 Quick Start 明确把该方式定位为本地开发与测试,容器被销毁时,未挂载到持久卷的数据也会随之消失。性能数据同样会受到 Docker Desktop、虚拟化、共享目录和本机其他进程的影响。

2.2 本地二进制路线能学到什么

本地路线会经过环境准备、软件下载、FE 配置、FE 启动、BE 注册、BE 启动、状态检查和数据验证。你会看到:

  • FE 和 BE 使用独立目录;
  • FE 依赖 JDK 17+;
  • priority_networks 决定节点使用哪张网卡通信;
  • FE 元数据与 BE 数据需要持久化目录;
  • FE 通过 9030 提供 MySQL 协议入口;
  • BE 通过 9050 向 FE 汇报心跳;
  • 进程日志与节点状态共同构成排障依据。

这些知识会直接进入 Day 21–25 的生产架构、容量规划、监控和故障排查。


三、环境准备:当前 4.x 基线需要更新旧口径

原培训材料中的部署章节使用过 nofile=65535,Java 部分同时出现 JDK 8、JDK 11 和 JDK 17+。这类口径对应较早版本。当前 Doris 4.x 官方 Quick Start 已经明确使用 JDK 17+,文件句柄示例提高到 1,000,000,并将 vm.max_map_count 设置为 2,000,000

Doris 4.x 环境检查清单
Doris 4.x 环境检查清单

3.1 操作系统与 CPU 架构

官方 4.x 手工部署文档给出的基础环境包括 CentOS 7+ 和 Ubuntu 22.04+。Quick Start 也支持主流 AMD64/ARM64 Linux 环境。实际选择时需要与下载包的架构保持一致:

uname -m
cat /etc/os-release
lscpu | egrep 'Architecture|Model name|CPU\(s\)'

输出为 x86_64 时选择 x86_64 安装包;输出为 aarch64 时选择 ARM64 安装包。服务器 CPU、容器镜像和 Doris 二进制架构必须一致。

学习环境建议至少准备 4 个 CPU 核心、8 GB 内存和 30–50 GB 可用磁盘。资源更小也可能启动,但 FE、BE、系统缓存和导入任务会互相挤压,实验结果容易出现抖动。生产容量需要结合数据量、写入速度、并发和 SLA 单独推算。

3.2 使用专用运行用户

官方 Quick Start 建议创建 Doris 专用用户,避免使用 root 长期运行服务。这样能够清楚划分安装目录、数据目录和日志权限,也能降低误操作影响。

sudo useradd -m -s /bin/bash doris
sudo mkdir -p /opt/doris /data/doris-meta /data/doris-storage
sudo chown -R doris:doris /opt/doris /data/doris-meta /data/doris-storage

后续命令默认以 doris 用户执行:

sudo -iu doris

3.3 安装并确认 JDK 17+

FE 使用 Java,BE 的部分功能和工具链也需要正确的 Java 环境。建议安装独立 JDK,并显式配置 JAVA_HOME

java -version
readlink -f "$(command -v java)"
echo "$JAVA_HOME"

Ubuntu 可以使用:

sudo apt-get update
sudo apt-get install -y openjdk-17-jdk mysql-client curl wget tar

CentOS/RHEL 系列可以使用:

sudo yum install -y java-17-openjdk-devel mysql curl wget tar

然后在用户环境或 Doris 配置中设置:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH="$JAVA_HOME/bin:$PATH"

不同发行版的实际路径可能不同,使用 readlink 或包管理器查询后再填写。不要照抄示例路径。

3.4 文件句柄:nofile

Doris 会打开大量 Segment、索引、日志、Socket 和临时文件。文件句柄过低时,进程可能启动正常,随着表和查询增加逐渐出现 Too many open files

当前 4.x Quick Start 示例为:

* soft nofile 1000000
* hard nofile 1000000

将其写入 /etc/security/limits.conf 后,需要重新登录运行用户,或者重新启动对应服务会话。验证方式:

ulimit -Sn
ulimit -Hn
cat /proc/$(pgrep -f DorisFE | head -1)/limits | grep -i 'open files'

最后一条命令需要在 FE 已经启动后执行。只修改配置文件却没有让新限制进入进程,问题仍会存在。

3.5 虚拟内存映射数量:vm.max_map_count

Doris 会使用大量内存映射区域。当前 Quick Start 设置:

sudo tee -a /etc/sysctl.conf >/dev/null <<'EOF'
vm.max_map_count = 2000000
EOF
sudo sysctl -p
sysctl vm.max_map_count

同一参数在文件里重复出现时,后面的值可能覆盖前面的值。生产变更应由系统配置管理工具统一维护,避免多次追加。

3.6 网络、时间与主机名

FE 与 BE 依赖稳定的节点地址。多网卡、云主机、容器、VPN、WSL2 和临时网卡环境中,程序自动选择的 IP 可能无法被其他节点访问。priority_networks 用 CIDR 指定通信网段,例如:

priority_networks = 10.10.10.0/24

检查命令:

ip -br addr
hostname -I
ss -lntp
nc -zv 10.10.10.11 9030
nc -zv 10.10.10.12 9050

节点时间也要保持一致。事务、日志、监控和故障分析都依赖时间线:

timedatectl status
chronyc tracking 2>/dev/null || true

3.7 磁盘目录

FE 元数据体量通常低于 BE 数据,但重要性很高。官方手工部署指南建议生产中把 FE 元数据放在独立持久化 SSD,并与 BE 数据盘分开。学习环境可以使用本地目录:

mkdir -p /data/doris-meta /data/doris-storage
chmod 750 /data/doris-meta /data/doris-storage

验证空间和权限:

df -h /data/doris-meta /data/doris-storage
lsblk -f
test -w /data/doris-meta && echo "meta writable"
test -w /data/doris-storage && echo "storage writable"

3.8 为什么两个内核参数会决定稳定性

nofilevm.max_map_count 看起来属于操作系统细节,实际会直接限制数据库能管理多少文件和内存区域。分析数据库会把一张逻辑表拆成分区、Tablet、Rowset、Segment、数据页和索引页,查询期间还会建立网络连接、临时文件、日志文件与缓存文件。数据量和并发增长后,单个 BE 同时打开的对象数量可能非常可观。

文件句柄耗尽时,错误可能出现在查询、导入、Compaction、日志轮转或副本修复的任意阶段。内存映射区域不足时,程序可能在加载库、映射文件或分配大块内存时失败。它们的共同特点是:小规模测试经常正常,业务放量后才暴露,因此部署阶段必须提前校验。

配置值还需要进入实际服务进程。limits.conf 对已经存在的 Shell 和进程不会自动生效,systemd 服务也可能有自己的 LimitNOFILE。建议把“配置文件中的值”和“进程实际限制”分开检查:

# Shell 当前限制
ulimit -Sn
ulimit -Hn

# FE 启动后的实际限制
FE_PID=$(pgrep -f 'DorisFE' | head -1)
cat "/proc/${FE_PID}/limits" | grep -i 'open files'

# BE 启动后的实际限制
BE_PID=$(pgrep -f 'doris_be' | head -1)
cat "/proc/${BE_PID}/limits" | grep -i 'open files'

系统参数的管理也要可审计。实验环境可以手工修改,生产环境建议通过 Ansible、SaltStack、镜像构建或基础设施代码统一配置,避免不同节点拥有不同基线。


四、路径 A:使用 Docker 五分钟启动

官方 Quick Start 的 Docker 路径由启动脚本完成。脚本内容和默认版本可能随官网更新,执行前应先打开脚本检查镜像、端口、数据卷和清理逻辑。

4.1 下载并授权脚本

从 Apache Doris 4.x Quick Start 页面下载 start-doris.sh,然后执行:

chmod 755 start-doris.sh

4.2 启动集群

官方文档当前示例:

bash start-doris.sh

也可以指定版本:

bash start-doris.sh -v 4.1.0

官网脚本的默认版本与示例版本会更新。课程网站应把版本号做成可替换变量,不要把旧版本长期写在复制命令里。

4.3 验证 FE 与 BE

mysql -uroot -P9030 -h127.0.0.1 \
  -e 'SELECT `host`, `join`, `alive` FROM frontends()'

mysql -uroot -P9030 -h127.0.0.1 \
  -e 'SELECT `host`, `alive` FROM backends()'

FE 的 joinalive 应为 true;BE 的 alive 应为 1 或 true。若本机没有 MySQL Client,也可以进入带有客户端的容器执行,或者先完成客户端安装。

4.4 Docker 路线的退出与重置

重置前先确认脚本创建了哪些容器和数据卷:

docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Ports}}'
docker volume ls

停止容器与删除数据卷是两类操作。停止后数据卷仍在,删除卷会清空实验数据。把这两类动作拆成 stop.shreset.sh,避免因为一条过于激进的命令丢失需要保留的结果。


五、路径 B:本地 FE/BE 完整部署

下面以一台 Linux 主机、一个 FE、一个 BE 为例。示例 IP 使用 127.0.0.1。在虚拟机、多网卡、云主机和 WSL2 环境中,应替换为 FE 与 BE 能够互相访问的实际地址。

5.1 下载与目录规划

从 Apache Doris 官方下载页选择 4.x 对应架构的二进制包,校验 SHA-512 后解压。以下使用通用变量,避免把某个版本写死:

export DORIS_VERSION="4.x.y"
export DORIS_HOME="/opt/doris/apache-doris-${DORIS_VERSION}"

cd /opt/doris
tar -xzf "apache-doris-${DORIS_VERSION}-bin-x64.tar.gz"
ln -sfn "apache-doris-${DORIS_VERSION}" current

实际包名以下载页为准。目录建议:

/opt/doris/current/          # 当前二进制软链接
/data/doris-meta/            # FE 元数据
/data/doris-storage/         # BE 数据
/var/log/doris/              # 可选:统一日志目录

通过软链接切换版本,能让升级脚本和服务配置保持固定路径。生产升级仍要遵守官方升级顺序、兼容测试和回滚要求。

5.2 配置 FE

编辑:

/opt/doris/current/fe/conf/fe.conf

最小学习配置:

JAVA_HOME = /opt/jdk-17
priority_networks = 127.0.0.1/32
meta_dir = /data/doris-meta

JAVA_HOME 使用真实路径。priority_networks 选择 FE 监听和对外发布的 IP。meta_dir 指向持久化目录。部分发行包也支持默认 doris-meta 目录,显式配置更利于理解和迁移。

启动 FE:

cd /opt/doris/current/fe
bin/start_fe.sh --daemon

查看日志:

tail -n 200 log/fe.log
tail -n 100 log/fe.out

确认端口:

ss -lntp | egrep ':8030|:9010|:9020|:9030'

连接 FE:

mysql -h127.0.0.1 -P9030 -uroot

初始 root 密码默认为空。实验环境完成后也建议立即设置密码:

SET PASSWORD = PASSWORD('ChangeMe_Strong_2026');

密码请按企业规范管理,不要把真实口令提交到 Git 仓库。

5.3 配置 BE

编辑:

/opt/doris/current/be/conf/be.conf

最小学习配置:

JAVA_HOME = /opt/jdk-17
priority_networks = 127.0.0.1/32
storage_root_path = /data/doris-storage

storage_root_path 是 BE 持久化数据路径。生产环境可能使用多盘与介质标签,具体语法应按目标版本官方文档配置。

5.4 注册 BE

连接 FE 后执行:

ALTER SYSTEM ADD BACKEND "127.0.0.1:9050";

9050 是 BE 的心跳服务端口。注册操作告诉 FE:这里有一个计划加入集群的 BE。此时 BE 即使尚未启动,FE 也会保留节点记录,状态暂时显示为不可用。

5.5 启动 BE

cd /opt/doris/current/be
bin/start_be.sh --daemon

查看日志:

tail -n 200 log/be.log
tail -n 100 log/be.out

检查端口:

ss -lntp | egrep ':8040|:8050|:8060|:9050|:9060'

不同版本可能还会使用额外内部端口,最终以 be.conf 和目标版本文档为准。

5.6 验证集群状态

SHOW FRONTENDS;
SHOW BACKENDS;

也可以使用 4.x 系统表函数进行更精简的检查:

SELECT host, `join`, alive FROM frontends();
SELECT host, alive FROM backends();

FE/BE 配置与默认端口速查
FE/BE 配置与默认端口速查

5.7 为什么要理解启动与注册顺序

FE 是集群元数据和控制入口,BE 需要知道向哪个 FE 汇报状态,FE 也需要保存 BE 的地址与心跳端口。官方 Quick Start 和完整手工部署文档在示例顺序上略有差异:快速路线先启动 BE 再注册,完整部署路线先注册 BE 再启动。两种方式最终都依赖 FE 中存在节点记录,以及 BE 能够通过网络建立心跳。

本课程采用“启动 FE → 注册 BE → 启动 BE → 验证心跳”的顺序,便于观察状态变化:

  1. FE 启动后,SHOW FRONTENDS 应显示本节点已加入;
  2. 执行 ALTER SYSTEM ADD BACKEND 后,SHOW BACKENDS 会出现目标地址,此时可能显示 Alive=false
  3. BE 启动并成功绑定通信 IP 后,心跳到达 FE,状态切换为 Alive=true
  4. 创建表以后,FE 会为 Tablet 选择该 BE,TabletNum 开始增长。

这段变化非常适合学习。它把“配置记录”“进程启动”“网络心跳”“数据分配”四个概念拆开。删除节点、扩容、下线和故障恢复也遵循类似思路:先识别控制面记录,再检查数据面进程和网络,最后确认副本与 Tablet 状态。

5.8 用一组命令保存部署证据

每次启动后可以执行:

mkdir -p evidence
{
  date -Is
  ps -ef | egrep 'DorisFE|doris_be' | grep -v grep
  ss -lntp | egrep ':8030|:9030|:9050|:8040|:8060|:9060'
} | tee evidence/process-and-ports.txt

mysql -h127.0.0.1 -P9030 -uroot   -e 'SHOW FRONTENDS' | tee evidence/show-frontends.txt

mysql -h127.0.0.1 -P9030 -uroot   -e 'SHOW BACKENDS' | tee evidence/show-backends.txt

证据文件能帮助你对比两次启动的差异,也能在求助社区或团队同事时提供完整上下文。仅发送一句“BE 起不来”很难定位,日志、配置、端口和状态输出能够显著缩短排查时间。


六、怎样确认集群真正可用

启动与验证的四层判据
启动与验证的四层判据

6.1 FE 需要关注哪些字段

SHOW FRONTENDS 输出字段较多,初学阶段重点看:

  • Join:节点是否已经加入 FE 元数据集群;
  • Alive:FE 是否存活;
  • IsMaster:当前节点是否是 Master;
  • Role:Follower 或 Observer;
  • LastHeartbeat:最近心跳时间;
  • ErrMsg:异常原因。

单 FE 实验环境中,该 FE 应当同时是 Master。多 FE 环境中,只有一个 Master,其他 Follower 参与元数据复制与选举,Observer 承担读扩展。

6.2 BE 需要关注哪些字段

SHOW BACKENDS 重点看:

  • Alive:心跳是否正常;
  • SystemDecommissioned:是否处于下线流程;
  • TabletNum:节点持有的 Tablet 数;
  • DataUsedCapacityAvailCapacity:数据量与可用容量;
  • LastHeartbeatLastStartTime:心跳和启动时间;
  • ErrMsg:最近错误。

新加入 BE 的 TabletNum 可能为 0。创建表和写入数据后才会产生 Tablet;多节点集群扩容后,Tablet 数量会随 Rebalance 逐步接近平均值。

6.3 端口速查

组件 默认端口 作用
FE 8030 HTTP、Web UI、Stream Load 入口
FE 9030 MySQL 协议查询端口
FE 9010 FE 元数据日志与选举通信
FE 9020 FE RPC
BE 8040 BE Web Server
BE 9050 心跳服务,FE 注册 BE 时使用
BE 9060 BE 内部服务
BE 8060 BRPC 与数据交换

防火墙只开放 9030,客户端可能能够连接,BE 心跳和 Stream Load 仍会失败。部署检查需要覆盖整个通信矩阵。

6.4 日志与状态要一起看

常用日志:

fe/log/fe.log
fe/log/fe.out
be/log/be.log
be/log/be.out

状态命令说明结果,日志解释过程。比如 BE Alive=false,状态表只能告诉你心跳失败;FE 日志可能显示连接超时,BE 日志可能显示绑定到了错误网卡,防火墙规则则说明 9050 被拦截。三类证据组合后才能形成可靠结论。


七、创建第一张表:先把最小闭环走通

Day 7 会系统学习 Duplicate、Aggregate、Unique 三种模型;Day 8 会深入分区、分桶与副本。今天使用一张最小 Duplicate Key 表,目标是完成部署验证。

7.1 创建数据库

CREATE DATABASE IF NOT EXISTS demo;
USE demo;

7.2 创建订单明细表

CREATE TABLE orders (
    order_id   BIGINT         NOT NULL,
    order_time DATETIME       NOT NULL,
    user_id    BIGINT         NOT NULL,
    region     VARCHAR(32)    NULL,
    status     VARCHAR(16)    NULL,
    amount     DECIMAL(18, 2) NOT NULL
)
DUPLICATE KEY(order_id, order_time)
DISTRIBUTED BY HASH(order_id) BUCKETS 1
PROPERTIES (
    "replication_num" = "1"
);

这里有三个需要提前理解的点:

  1. DUPLICATE KEY 保留每一行明细,Key 在本课主要承担排序作用;
  2. BUCKETS 1 适合单 BE、小数据实验,生产桶数需要按数据量和并行度评估;
  3. 单 BE 环境无法放置三个副本,因此显式设置 replication_num=1

7.3 查看表结构

DESC orders;
SHOW CREATE TABLE orders;
SHOW TABLETS FROM orders;

SHOW CREATE TABLE 能看到 Doris 最终保存的完整 DDL。SHOW TABLETS 可以帮助你把逻辑表映射到 Tablet 和 BE。

7.4 使用 INSERT 写入几行数据

INSERT INTO orders VALUES
(1001, '2026-08-16 10:00:00', 20001, 'East',  'PAID',   199.90),
(1002, '2026-08-16 10:03:00', 20002, 'North', 'PAID',   299.00),
(1003, '2026-08-16 10:05:00', 20001, 'East',  'REFUND',  59.90),
(1004, '2026-08-16 10:08:00', 20003, 'South', 'PAID',   499.00);

查询:

SELECT * FROM orders ORDER BY order_id;

SELECT
    DATE(order_time) AS dt,
    COUNT(*) AS order_count,
    SUM(amount) AS total_amount
FROM orders
GROUP BY DATE(order_time)
ORDER BY dt;

这个结果验证了 FE 解析和规划、BE 写入和读取、Tablet 路由、列式执行与结果返回的完整链路。

7.5 这条 DDL 在集群内部创建了什么

执行 CREATE TABLE 后,FE 首先校验数据库、字段类型、Key 顺序、分桶方式、副本数和属性,然后把表结构写入元数据。对于这张表,BUCKETS 1 会在每个分区内创建一个逻辑 Tablet。表没有显式分区,因此使用系统生成的默认分区。replication_num=1 让这个 Tablet 只需要在一个 BE 上放置一个副本。

BE 接到建表相关元数据后,会准备 Tablet 目录。真正写入数据时,每个批次形成新的版本和 Rowset,Rowset 内部包含一个或多个 Segment。后续查询由 FE 生成计划并选择健康副本,BE 扫描 Segment、读取需要的列、执行过滤和聚合。

这解释了几个常见现象:

  • 刚创建空表时,SHOW TABLETS 已能看到 Tablet;
  • SHOW BACKENDSTabletNum 会随着建表变化;
  • 每次小批写入都可能增加版本与文件,过度碎片化会给 Compaction 带来压力;
  • 删除并重建表会产生新的表 ID 和 Tablet ID;
  • 单 BE 实验环境无法验证副本调度、节点故障和 Rebalance。

今天只观察这些对象,不深入参数。Day 8 会把排序键、分区、分桶、副本与 Tablet 设计串成完整方法,Day 19–20 会继续下钻 Rowset、Segment、版本和 Compaction。

7.6 MySQL 协议连接带来了哪些便利

Doris FE 默认在 9030 提供 MySQL 网络协议服务。命令行客户端、DataGrip、DBeaver、JDBC 驱动和许多 BI 工具都能沿用成熟生态。常见连接格式:

mysql -h FE_IP -P 9030 -u USER -p

Java 应用可以使用 MySQL JDBC Connector:

jdbc:mysql://FE_IP:9030/demo
  ?useUnicode=true
  &characterEncoding=utf8
  &serverTimezone=Asia/Shanghai
  &useSSL=false
  &allowPublicKeyRetrieval=true

连接成功只代表网络协议和认证通过。SQL 方言、事务能力、索引、存储引擎和系统表仍以 Doris 语义为准。迁移 MySQL 应用时需要逐条验证 DDL、DML、函数、事务和查询行为,不能只根据“客户端能连上”判断兼容完成。


八、完成第一次 Stream Load

INSERT 适合少量测试数据和 SQL 内部转换。真实数据导入通常需要批量接口。Stream Load 通过一次 HTTP PUT 把本地文件或字节流写入 Doris,FE 将请求重定向给协调 BE,协调 BE 解析数据、分发到 Tablet 所在节点,并在同一个事务中提交。

建表、Stream Load 与查询闭环
建表、Stream Load 与查询闭环

8.1 准备 CSV

创建 orders.csv

1005,2026-08-16 10:10:00,20004,West,PAID,88.80
1006,2026-08-16 10:12:00,20005,East,PAID,168.00
1007,2026-08-16 10:15:00,20006,North,CANCELLED,39.90

列顺序与表结构保持一致。

8.2 执行 Stream Load

curl --location-trusted \
  -u 'root:ChangeMe_Strong_2026' \
  -H 'Expect: 100-continue' \
  -H "label:day5_orders_$(date +%s)" \
  -H 'column_separator:,' \
  -T orders.csv \
  http://127.0.0.1:8030/api/demo/orders/_stream_load

关键参数:

  • --location-trusted:跟随 FE 到 BE 的重定向,并在重定向后继续携带认证信息;
  • Expect: 100-continue:先发送头部,让服务端完成认证和事务准备,再发送文件;
  • label:本次导入事务的唯一标识,用于幂等与重试判断;
  • column_separator:CSV 列分隔符;
  • -T:上传本地文件;
  • 8030:FE HTTP 端口。

8.3 如何判断成功

Stream Load 返回 JSON,重点读取:

  • Status:应为 Success
  • NumberTotalRows:解析到的总行数;
  • NumberLoadedRows:成功加载行数;
  • NumberFilteredRows:被过滤的行数;
  • NumberUnselectedRows:被 WHERE 等条件排除的行数;
  • LoadBytes:本次数据量;
  • BeginTxnTimeMsWriteDataTimeMsCommitAndPublishTimeMs:各阶段耗时。

本次实验期望:

Status = Success
NumberLoadedRows = NumberTotalRows = 3
NumberFilteredRows = 0

然后查询:

SELECT COUNT(*) AS total_rows, SUM(amount) AS total_amount
FROM demo.orders;

8.4 Label 的意义

成功的 Label 再次提交会被 Doris 拒绝,从而避免同一批数据因为网络超时或客户端重试被重复写入。失败任务的 Label 在满足条件时可以重新使用。业务系统应把 Label 与批次、文件或上游事务建立稳定映射,随机字符串虽然能规避冲突,却无法帮助追踪批次。

8.5 脏数据怎样处理

默认 max_filter_ratio=0,出现不合格行时整批可能失败。返回 JSON 中通常包含 ErrorURL,可以使用浏览器或 curl 查看具体错误行。初学阶段建议保持严格模式,先修复数据,再考虑允许过滤比例。生产数据质量策略需要明确:哪些字段允许为空,哪些错误可以过滤,哪些错误必须阻断上游。

8.6 一次 Stream Load 在内部经过哪些步骤

理解内部路径有助于解释超时、重定向、Label 冲突和部分节点故障。

  1. 客户端向 FE 的 HTTP 端口发送 PUT 请求和请求头;
  2. FE 完成认证、选择一个协调 BE,并通过 HTTP 重定向返回该 BE 地址;
  3. curl --location-trusted 跟随重定向,把数据体发送到协调 BE;
  4. 协调 BE 根据格式解析 CSV,执行列映射、类型转换和数据质量检查;
  5. 数据按照分区和分桶规则路由到持有目标 Tablet 的 BE;
  6. FE 管理本次导入事务,所有参与节点写入成功后提交;
  7. 新版本发布,查询才能看到这批数据;
  8. 协调 BE 返回 JSON,客户端依据状态和行数决定成功、重试或报警。

其中任何环节都可能成为瓶颈。请求在 FE 阶段失败,常见原因是认证、数据库和表不存在;重定向后失败,常见原因是客户端无法访问 BE 的 8040 端口;解析阶段失败,多与格式、分隔符和类型有关;分发阶段失败,需要检查目标 BE、网络和磁盘;提交阶段超时,需要结合事务状态确认数据是否已经可见。

同步返回不代表客户端可以忽略超时后的状态。网络在服务端提交成功后断开,客户端可能没有收到成功 JSON。此时依靠稳定 Label 查询或重试,才能避免重复数据。生产写入程序需要把 Label、源批次、返回结果、重试次数和最终状态保存到日志或任务系统中。

8.7 INSERT 与 Stream Load 怎样分工

方式 适合场景 优点 注意事项
INSERT VALUES 少量测试行、手工验证 语法直观,便于快速观察 不适合高频逐行写入
INSERT SELECT Doris 内部表间加工 能利用 SQL 完成转换和聚合 关注资源、事务与目标表模型
Stream Load 本地文件、服务批次、实时微批 同步响应、事务原子、Label 幂等 需要处理重定向、格式和错误行
Connector Flink、Spark、Kafka 等持续链路 与计算或消息系统集成 版本兼容、Checkpoint 与重试需验证

今天使用前两类完成入门。Day 9–10 会系统学习批量导入、实时同步和 Connector。


九、生成 1 万行实验数据

今天的交付要求包含一万行数据。可以使用 Python 标准库生成固定种子 CSV:

#!/usr/bin/env python3
import csv
import random
from datetime import datetime, timedelta

random.seed(20260816)
start = datetime(2026, 8, 1, 0, 0, 0)
regions = ["East", "North", "South", "West"]
statuses = ["PAID", "PAID", "PAID", "REFUND", "CANCELLED"]

with open("orders-10000.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    for i in range(10_000):
        order_id = 1_000_000 + i
        order_time = start + timedelta(seconds=i * 37)
        user_id = 20_000 + random.randint(1, 2_000)
        region = random.choice(regions)
        status = random.choice(statuses)
        amount = round(random.uniform(1, 2_000), 2)
        writer.writerow([
            order_id,
            order_time.strftime("%Y-%m-%d %H:%M:%S"),
            user_id,
            region,
            status,
            amount,
        ])

执行:

python3 generate_orders.py
wc -l orders-10000.csv
sha256sum orders-10000.csv

记录 SHA-256 能确认所有学习者使用了同一份数据。然后使用新的 Label 执行 Stream Load。

验证:

SELECT COUNT(*) FROM demo.orders;

SELECT region, status, COUNT(*) AS cnt, SUM(amount) AS amount
FROM demo.orders
GROUP BY region, status
ORDER BY region, status;

如果表中已经有前面的 7 行,最终行数应为 10007。更适合自动化的方式是先执行 TRUNCATE TABLE orders,再统一导入一万行,让验收结果固定为 10000。


十、常见问题:按“主机—进程—集群—数据”顺序排查

Doris Quick Start 常见故障定位树
Doris Quick Start 常见故障定位树

10.1 FE 无法启动

JDK 或 JAVA_HOME 错误

现象:fe.out 中出现 Java 不存在、版本不兼容、类加载失败。

检查:

java -version
$JAVA_HOME/bin/java -version

处理:统一到 JDK 17+,保证启动脚本和 fe.conf 使用同一个 Java 路径。

元数据目录不可写

现象:创建文件失败、BDBJE 初始化失败、目录权限错误。

检查:

ls -ld /data/doris-meta
test -w /data/doris-meta && echo OK

处理:修复目录所有者和权限,确认磁盘没有只读挂载或空间耗尽。

端口冲突

检查:

ss -lntp | egrep ':8030|:9010|:9020|:9030'

处理:停止冲突进程,或者按版本文档调整 FE 端口,并同步更新防火墙与客户端配置。

10.2 BE 已启动,Alive=false

这是初学者最常见的问题之一。

priority_networks 选择了错误 IP

BE 可能把 Docker 网桥、VPN 网卡或回环地址注册给 FE。FE 无法从自身网络访问该地址,心跳持续失败。

检查:

ip -br addr
grep -n priority_networks fe/conf/fe.conf be/conf/be.conf

FE 与 BE 的网段配置需要匹配真实可达地址。WSL2 中不同发行版的回环网络可能隔离,直接使用 127.0.0.1/32 会造成注册或心跳问题。

9050 被防火墙拦截

nc -zv BE_IP 9050

同时检查 8040、8060、9060 等 BE 端口。只开放 MySQL 查询端口无法形成完整集群。

数据目录不可写或磁盘异常

查看 be.logbe.out,确认 storage_root_path 存在、可写、有空间,文件系统没有进入只读状态。

10.3 MySQL Client 连接失败

检查四项:

  1. FE 的 9030 是否监听;
  2. 客户端访问的是 FE 地址;
  3. 防火墙与安全组是否放行;
  4. 用户名和密码是否正确。
nc -zv FE_IP 9030
mysql -hFE_IP -P9030 -uroot -p

Doris 兼容 MySQL 网络协议,协议兼容不等于所有 MySQL 管理语句和存储引擎语义完全相同。Day 6 会系统讨论这个边界。

10.4 建表报副本不足

单 BE 环境中,如果表使用默认三副本,建表会失败或无法分配副本。实验表显式设置:

PROPERTIES ("replication_num" = "1")

生产环境应配置满足高可用目标的副本数,并保证有足够 BE 和故障域承载这些副本。

10.5 Stream Load 返回 307、认证失败或无法访问 BE

FE 会把请求重定向到 BE。curl 需要使用 --location-trusted。Kubernetes 或跨网络部署中,FE 返回的 BE 地址可能只在集群内部可访问,需要额外配置外部可达的 BE 服务或代理地址。

10.6 Label 已存在

成功批次复用同一个 Label 会被拒绝。先确认上次任务是否已经提交,再决定跳过、查询结果或创建新批次。不能在不核对数据的情况下直接换 Label 重试,否则可能重复导入。

10.7 导入存在过滤行

查看响应中的 NumberFilteredRowsErrorURL。常见原因包括:

  • CSV 列数和表结构不一致;
  • 日期格式错误;
  • 字符串写入数值列;
  • 非空列收到空值;
  • 分隔符出现在字段内部;
  • 字符编码不一致。

先定位具体行,再决定修改源数据、列映射、转换表达式或容错策略。

10.8 建立可复用的排障记录格式

每次问题建议记录以下字段:

发生时间:
Doris 版本与提交号:
部署模式:Docker / 二进制 / Kubernetes:
节点拓扑:
最近变更:
用户可见症状:
失败命令与完整返回:
FE/BE 状态:
相关日志时间段:
CPU / 内存 / 磁盘 / 网络:
已经尝试的操作:
当前判断与下一步:

“最近变更”常常是最有价值的线索:升级 JDK、修改网卡、调整安全组、迁移数据目录、清理磁盘、变更密码、重启主机,都可能改变启动和通信行为。记录完整命令和原始返回,避免只保留经过转述的错误描述。

排障过程中一次只改变一个变量。先复制配置和日志,再执行修改;修改后重复同一验证命令;问题解决后把原因、修复和预防措施写入仓库。这样形成的案例会成为团队自己的 Doris 运行手册。


十一、停止、启动与重置

手工环境中,建议先停止 BE,再停止 FE:

cd /opt/doris/current/be
bin/stop_be.sh

cd /opt/doris/current/fe
bin/stop_fe.sh

重新启动:

/opt/doris/current/fe/bin/start_fe.sh --daemon
/opt/doris/current/be/bin/start_be.sh --daemon

正常停止不会删除元数据和表数据。重置实验环境时,必须确认路径变量正确,再清理:

# 危险操作:仅用于明确的学习环境
rm -rf /data/doris-meta/*
rm -rf /data/doris-storage/*

生产环境严禁把这类命令放进无确认的脚本。更安全的实验方式是给每个环境单独目录,并在 reset.sh 中检查环境标识、路径前缀和交互确认。


十二、把今天的步骤整理成可复现实验仓库

可复现实验环境仓库结构
可复现实验环境仓库结构

建议建立以下目录:

doris-lab/
├── README.md
├── .env.example
├── scripts/
│   ├── check-env.sh
│   ├── start.sh
│   ├── verify.sh
│   ├── stop.sh
│   └── reset.sh
├── conf/
│   ├── fe.conf.example
│   └── be.conf.example
├── sql/
│   ├── 00-create.sql
│   ├── 01-insert.sql
│   └── 02-check.sql
├── data/
│   └── orders-10000.csv
└── evidence/
    ├── environment.txt
    ├── node-status.txt
    ├── stream-load.json
    └── query-result.txt

12.1 check-env.sh 应记录什么

#!/usr/bin/env bash
set -euo pipefail

{
  date -Is
  uname -a
  cat /etc/os-release
  java -version
  echo "JAVA_HOME=${JAVA_HOME:-}"
  echo "nofile_soft=$(ulimit -Sn)"
  echo "nofile_hard=$(ulimit -Hn)"
  sysctl vm.max_map_count
  free -h
  df -h
  ip -br addr
} 2>&1 | tee evidence/environment.txt

12.2 verify.sh 应验证什么

#!/usr/bin/env bash
set -euo pipefail

MYSQL=(mysql -h127.0.0.1 -P9030 -uroot -p"${DORIS_PASSWORD}")

"${MYSQL[@]}" -e 'SELECT host, `join`, alive FROM frontends()' \
  | tee evidence/frontends.txt

"${MYSQL[@]}" -e 'SELECT host, alive FROM backends()' \
  | tee evidence/backends.txt

"${MYSQL[@]}" -e 'SELECT COUNT(*) FROM demo.orders' \
  | tee evidence/query-result.txt

密码通过环境变量或密钥管理注入,避免提交明文。

12.3 可复现的验收标准

换一台满足要求的 Linux 机器,按照 README 执行后,应该得到:

  • 相同版本的 Doris;
  • 相同的 FE/BE 配置模板;
  • FE 和 BE 正常状态;
  • 相同 SHA-256 的数据种子;
  • 相同表结构;
  • 相同行数和聚合结果;
  • 完整环境、导入和查询证据。

这套仓库会继续使用到 Day 30。后续每一天只增加新的 SQL、数据集、配置或实验脚本。


十三、从学习拓扑走向生产,还缺哪些环节

今天完成的是功能底座。生产上线前至少还要补齐:

  1. FE 高可用:配置三个参与选举的 Follower,使用稳定入口访问 FE;
  2. BE 多节点与多副本:根据容量和故障域规划节点,核心数据通常使用多副本;
  3. 专用磁盘与目录:FE 元数据、BE 数据、日志和临时空间进入明确磁盘规划;
  4. 负载入口:客户端不能长期写死单个 FE 地址,需要 VIP、负载均衡或域名;
  5. 监控与告警:接入 Prometheus、Grafana,观察节点、查询、导入、内存、磁盘与 Compaction;
  6. 备份与恢复:备份 FE 元数据和业务数据,定期演练恢复;
  7. 安全治理:设置密码、最小权限、网络隔离、审计和密钥管理;
  8. 容量与性能 POC:使用真实数据、SQL、并发、写入和故障场景验证;
  9. 服务托管:使用 systemd、Supervisor 或 Doris Operator 管理自动拉起;
  10. 版本治理:固定目标版本,校验包完整性,建立升级和回滚门禁。

这些内容会在 Day 21–25 展开。现在只需牢记:单机环境提供学习效率,生产环境提供业务承诺。


十四、今日实践任务

完成一个《可复现 Doris 实验环境仓库》,并提交以下结果:

任务 1:环境检查

  • 操作系统与 CPU 架构;
  • JDK 版本和 JAVA_HOME
  • soft/hard nofile;
  • vm.max_map_count
  • 内存与磁盘;
  • FE/BE 使用 IP;
  • 关键端口占用情况。

任务 2:部署与节点验证

  • 启动 FE 和 BE;
  • 保存 SHOW FRONTENDS
  • 保存 SHOW BACKENDS
  • 标出 FE Master、Join、Alive;
  • 标出 BE Alive、LastHeartbeat、TabletNum。

任务 3:数据闭环

  • 创建 demo.orders
  • 使用 Python 生成 10,000 行 CSV;
  • 执行 Stream Load;
  • 保存完整 JSON 响应;
  • 确认加载行数为 10,000、过滤行数为 0;
  • 执行分地区、分状态聚合并保存结果。

任务 4:重置验证

  • 停止集群;
  • 按实验规则重置;
  • 重新启动;
  • 再次创建表并导入同一数据集;
  • 确认最终结果一致。

验收表

项目 通过条件
FE Join=true、Alive=true、Master 可识别
BE Alive=true、心跳时间持续更新
建表 SHOW CREATE TABLE 与仓库 DDL 一致
Stream Load Status=Success,加载 10,000 行,过滤 0 行
查询 COUNT=10,000,聚合结果可复现
重置 清理并重建后得到相同结果
证据 环境、节点、导入和查询输出完整保存

十五、Knowledge Check

题目 1

当前 Doris 4.x 本地部署推荐的 Java 基线是什么?

答案要点: JDK 17+。实际路径通过 JAVA_HOME 显式配置,并确认启动脚本使用同一 JDK。

题目 2

priority_networks 解决什么问题?

答案要点: 它使用 CIDR 帮助 FE/BE 选择正确的通信网卡 IP,避免多网卡、VPN、容器或云环境中发布不可达地址。

题目 3

为什么看到 FE/BE 进程后仍不能宣布集群成功?

答案要点: 进程存在只说明程序尚未退出。还要验证 FE Join/Alive/Master、BE 心跳 Alive,以及建表、写入和查询结果。

题目 4

单 BE 实验环境为什么设置 replication_num=1

答案要点: 单个 BE 无法承载多个独立副本。生产环境需要足够 BE 承载多副本高可用策略。

题目 5

Stream Load 中 label 的作用是什么?

答案要点: 标识一次导入事务,支持幂等和重试判断。成功 Label 重复提交会被拒绝,防止同一批次重复写入。

题目 6

Stream Load 返回成功时要核对哪些字段?

答案要点: StatusNumberTotalRowsNumberLoadedRowsNumberFilteredRows,必要时查看 ErrorURL 和阶段耗时。

题目 7

当前 Quick Start 对 nofile 和 vm.max_map_count 的示例值是多少?

答案要点: nofile soft/hard 设为 1,000,000,vm.max_map_count 设为 2,000,000。修改后需要确认新值进入实际进程环境。

题目 8

Docker 快速启动为什么不能直接作为生产部署方案?

答案要点: Quick Start 面向本地开发和测试,默认拓扑、数据持久化、资源隔离、高可用、监控和故障恢复都没有达到生产要求。


十六、本日总结

今天完成了 Apache Doris 学习路径中的第一次完整落地。

我们建立了四层验收方法:主机环境、进程状态、集群状态和数据闭环。Docker 路线帮助学习者快速获得可查询集群,本地二进制路线进一步解释了 FE、BE、配置、端口、注册、心跳和日志。

当前 4.x 部署基线需要使用 JDK 17+,提高文件句柄上限,并设置足够的 vm.max_map_countpriority_networks 决定节点发布的通信地址,FE 元数据目录和 BE 数据目录决定持久化位置。节点进程、集群状态和读写结果需要同时验证。

第一张 Duplicate Key 表完成了 DDL、Tablet、副本和查询链路验证。INSERT 适合少量测试数据,Stream Load 通过 HTTP PUT、Label 和事务完成批量同步导入。返回 JSON 是导入验收的核心证据。

最后,我们把配置、脚本、SQL、数据种子和证据整理为可复现实验仓库。接下来的课程都将在这套底座上继续推进。

明天进入 Day 6:Doris SQL、数据类型与函数体系。我们会从协议兼容、类型语义、精度、时间、复杂类型和函数分类出发,建立一套能够支撑正确建模的 SQL 基础。


官方资料

  1. Apache Doris 4.x:5-Minute Quick Start
    https://doris.apache.org/docs/4.x/getting-started/quick-start/
  2. Apache Doris 4.x:Manually Deploying an Integrated Storage-Compute Cluster
    https://doris.apache.org/docs/4.x/install/deploy-manually/integrated-storage-compute-deploy-manually/
  3. Apache Doris 4.x:Installation and Deployment
    https://doris.apache.org/docs/4.x/install/intro/
  4. Apache Doris 4.x:Connecting via MySQL Protocol
    https://doris.apache.org/docs/4.x/connection-integration/mysql-proto/
  5. Apache Doris 4.x:Stream Load
    https://doris.apache.org/docs/4.x/key-features/stream-load/
  6. Apache Doris 4.x:Load FAQ
    https://doris.apache.org/docs/4.x/faq/load-faq/
  7. Apache Doris 4.x:Common Operations FAQ
    https://doris.apache.org/docs/4.x/faq/install-faq/

资料核对日期:2026-08-16。命令、版本号、下载包名称与配置项可能随 Doris 版本更新,正式执行前需要再次核对目标版本官方文档。