【摘要】这次整理的是日志平台每天的固定动作。原先巡检要开好几个窗口来回看,现在压成一条可定时执行的命令链:连 Master FE,依次跑 SHOW BACKENDS、SHOW FRONTENDS、SHOW PROC '/statistic' 做节点与库级体检,再按 Alive、MaxDiskUsedPct、TabletNum 三列做判定;慢查询走 __internal_schema.audit_log 配 SHOW PROFILELIST / SHOW PROFILE 定位到算子;扩容是启动 BE 进程加一条 ALTER SYSTEM ADD BACKEND。环境是 3 个 FE 加多个 BE 的 Apache Doris 3.x 集群,客户端是 MySQL 8.0。网易公开实践里把 streaming_label_keep_max_second 与 label_clean_interval_second 从默认的 12 小时和 1 小时收到 300 秒,FE JVM 内存曲线恢复平稳(出处见文末)。下面给环境、巡检命令链、慢查询排查、扩缩容命令模板、脚本化写法与扩容后的验证步骤。
一、先说结论
巡检这件事,我的判断标准不是"要不要每天跑",而是"能不能在五分钟内跑完并且结论可判定"。下面这几条是我压缩命令链之前逐条对照过的:
| 信号 | 我这边当时的表现 | 处理方向 |
|---|---|---|
| 巡检靠人肉记命令 | 每天开几个窗口,先查健康再查磁盘再查分片 | 收敛成一条脚本,输出只要异常行 |
| 节点状态没有判定标准 | 看到磁盘用了 70% 不敢判断要不要处理 | 把阈值写进脚本,输出只有达标和不达标 |
| 扩缩容每次临时翻文档 | 加节点前现查命令、现确认端口 | 固定成命令模板,只改 IP 和端口 |
| 慢查询排查要跨多个观测面 | 一边看监控一边翻日志,对不上时间戳 | 审计表与执行画像用同一个 query_id 串起来 |
| 值班交接靠师傅带 | 新人跟一个月才敢独立值班 | 把命令与阈值写成脚本,交接即交付脚本 |
| 集群在长、人力没长 | 节点数翻倍,值班还是那几个人 | 让巡检覆盖面跟着命令数走,不跟着节点数走 |
反过来,如果你的集群规模稳定在个位数节点、查询形态也很固定,那把每日巡检整套照搬意义不大,挑节点存活和磁盘水位两项就够,剩下的每周看一次。
二、问题怎么产生
2.1 成本不在命令本身,在"每天要不要想一遍"
一条 SHOW BACKENDS 打出来不到一秒,真正耗时的是打完之后人要在脑子里过一遍:这几列代表什么、今天的值和昨天比有没有变化、这个变化要不要处理。命令不固化,判断标准就不固化;判断标准不固化,同一次巡检两个人能得出两个结论。
我把命令链写进脚本之后,脚本只输出"命中异常条件的行",判断这件事就从人脑搬到了 WHERE 里,这是收益最大的一步。
2.2 节点是有中间态的,单帧快照判断不了
BE 节点不是简单的"活着/挂了"。它至少有三种需要连续观察的状态:Alive 为 false 但可能只是心跳抖动;SystemDecommissioned 为 true 表示正在安全下线;TabletNum 从几千往下降,说明数据正在往别的节点搬。这三种状态的处置动作完全不同:第一种先观察,第二种不能中断,第三种要盯进度。
也就是说,巡检命令链至少要能"看状态 + 看趋势",只看一次是不够的,所以我把它做成了每天固定时间跑、输出留档。
2.3 命令入口分散,交接成本被低估
节点信息在 SHOW BACKENDS、元数据节点在 SHOW FRONTENDS、库级体量在 SHOW PROC '/statistic'、副本健康在 SHOW PROC '/cluster_health/tablet_health'。这些都在同一个客户端里能查到,问题是"知道该查哪一个"这件事本身是经验。经验不落文档,人一换就断。
三、怎么做:实操路径
3.1 环境与连接
| 组件 | 版本 / 规格 | 用途 |
|---|---|---|
| Apache Doris | 3.x,FE 与 BE 分离部署 | 被巡检的日志集群 |
| FE 数量 | 3 个(1 Master + 2 Follower) | 元数据与查询接入 |
| MySQL 客户端 | 8.0.x | 连 FE 的 9030 端口执行语句 |
| 巡检脚本 | bash + mysql -N -B | 定时执行并留档输出 |
| 审计与 Profile | enable_audit_plugin 已开启 |
慢查询排查入口 |
巡检脚本固定连 Master FE。先确认当前连的是不是 Master,再执行后续语句,否则部分 PROC 目录会报错或数据不全:
perl
# 确认 FE 角色(QueryPort 默认 9030,EditLogPort 默认 9010)
mysql -h 192.168.1.10 -P 9030 -u root -p -e "SHOW FRONTENDS\G" | grep -E "Role|IsMaster|Alive|QueryPort"
# 连上之后切到日志库
mysql -h 192.168.1.10 -P 9030 -u root -p log_db
3.2 每日巡检的三条主语句
sql
-- 1) BE 节点:存活、磁盘水位、分片承载量、是否正在下线
SHOW BACKENDS;
-- 2) FE 节点:角色、是否 Master、存活、版本
SHOW FRONTENDS;
-- 3) 库级体量与副本统计:TabletNum、ReplicaNum
SHOW PROC '/statistic';
SHOW BACKENDS 返回的列不少,我固定看这几列:Alive(心跳是否正常)、MaxDiskUsedPct(所有磁盘里用得最多的那块)、UsedPct(整体水位)、TabletNum(承载量,也是下线进度指标)、SystemDecommissioned(是否在安全下线)、ErrMsg(心跳失败时的错误信息)、HeartbeatFailureCounter(连续失败次数)。官方文档说明连续失败次数超过 FE 的 max_backend_heartbeat_failure_tolerance_count(默认值 1)时 Alive 会被置为 false。
比 SHOW BACKENDS 更好用的是表函数 backends(),可以直接在 WHERE 里写判定条件:
sql
-- 只输出命中异常条件的节点
SELECT Host, Alive, UsedPct, MaxDiskUsedPct, TabletNum, SystemDecommissioned, ErrMsg
FROM backends()
WHERE Alive = false
OR MaxDiskUsedPct > 80
OR HeartbeatFailureCounter > 0;
-- 下线进度:按 TabletNum 降序看谁还没搬完
SELECT Host, TabletNum, SystemDecommissioned
FROM backends()
WHERE SystemDecommissioned = true
ORDER BY TabletNum DESC;
3.3 慢查询:从"哪条慢"到"慢在哪个算子"
审计日志插件默认关闭,第一步是打开:
sql
SET GLOBAL enable_audit_plugin = true;
USE __internal_schema;
SELECT query_id, time, user, db, query_time, scan_rows, scan_bytes, cpu_time_ms, stmt
FROM audit_log
WHERE is_query = 1
AND query_time > 3000
ORDER BY query_time DESC
LIMIT 20;
拿到 query_id 之后看执行画像:
sql
SET enable_profile = true;
-- 重跑一次待排查的查询
SELECT service, level, COUNT(*) FROM log_db.app_log
WHERE log_time >= NOW() - INTERVAL 1 DAY
GROUP BY service, level ORDER BY 3 DESC LIMIT 10;
-- 列出最近的 Profile,再按 query_id 拉算子级耗时
SHOW PROFILELIST;
SHOW PROFILE WHERE query_id = 'b7c2a1e04f3d4a8b-9d1f0e7c5a2b3e46';
审计表负责"哪条慢、慢在什么量级",Profile 负责"慢在哪个算子",两者用同一个 query_id 串起来,不用跨系统对时间戳。
3.4 扩容命令模板
sql
-- BE:先在新机器上启动进程(be/bin/start_be.sh --daemon),再注册
-- 端口是 BE 的心跳端口,默认 9050
ALTER SYSTEM ADD BACKEND "192.168.1.21:9050";
-- FE:按角色注册,端口为 edit_log 端口,默认 9010
ALTER SYSTEM ADD FOLLOWER "192.168.1.31:9010";
ALTER SYSTEM ADD OBSERVER "192.168.1.32:9010";
注册完之后数据由后台逐步均衡,不需要人工干预分布,但要盯进度:
sql
SHOW PROC '/cluster_balance/pending_tablets';
SHOW PROC '/cluster_health/tablet_health';
SHOW PROC '/diagnose';
SHOW PROC '/diagnose' 会按项给出 ERROR / WARNING,覆盖 Tablet Health、BeLoad Balance、Disk Balance、Colocate Group Stable 等,扫一眼就知道有没有要处理的项。
3.5 缩容:用 DECOMMISSION
sql
ALTER SYSTEM DECOMMISSION BACKEND "192.168.1.21:9050";
-- 进度:SystemDecommissioned 为 true 表示正在下线,TabletNum 持续下降
SELECT Host, TabletNum, SystemDecommissioned FROM backends();
-- 需要中止时
CANCEL DECOMMISSION BACKEND "192.168.1.21:9050";
官方对两种方式的对比写得很清楚:DROP 立即生效、可能造成数据丢失,不推荐生产使用;DECOMMISSION 先把数据迁走再下线。迁移耗时官方给的预期是小时级到一天不等,建议安排在业务低峰期。
3.6 把命令链脚本化
bash
#!/usr/bin/env bash
# daily_check.sh ------ 每日巡检命令链,输出只保留异常行
FE_HOST=192.168.1.10
FE_PORT=9030
LOG=/var/log/doris_daily_check.log
MYSQL="mysql -h ${FE_HOST} -P ${FE_PORT} -u root -p${PASS} -N -B"
{
echo "===== $(date '+%F %T') ====="
echo "--- 异常 BE 节点 ---"
$MYSQL -e "SELECT Host, Alive, MaxDiskUsedPct, TabletNum, SystemDecommissioned, ErrMsg \
FROM backends() WHERE Alive = false OR MaxDiskUsedPct > 80;"
echo "--- FE 角色与存活 ---"
$MYSQL -e "SHOW FRONTENDS;"
echo "--- 库级体量 ---"
$MYSQL -e "SHOW PROC '/statistic';"
echo "--- 集群诊断 ---"
$MYSQL -e "SHOW PROC '/diagnose';"
} >> "${LOG}" 2>&1
输出留档之后,第二天的巡检不只是"今天有没有问题",还能回答"这个问题是从哪天开始的"。我给这份日志保留了 90 天,排查容量趋势时比监控曲线还好用。
3.7 关键参数与建议值
| 参数名 | 我用的值 | 作用 | 适用场景 |
|---|---|---|---|
enable_audit_plugin |
true |
审计写入 __internal_schema.audit_log |
需要按 query_time 排查慢查询 |
audit_plugin_max_batch_interval_sec |
60(默认) | 审计批量写入的时间上限 | 审计开销可控,一般不动 |
audit_plugin_max_batch_bytes |
50MB(默认) | 审计批量写入的字节上限 | 审计量大的集群按需评估 |
balance_slot_num_per_path |
按盘型调 | 控制副本迁移速率 | 迁移期间影响在线查询时调小 |
tablet_repair_delay_factor_second |
60(默认) | 副本修复按优先级延迟触发 | BE 短暂离线后修复任务集中 |
streaming_label_keep_max_second |
300 | Label 保留时长,默认 12 小时 | 高并发 Stream Load,FE 内存上涨 |
label_clean_interval_second |
300 | Label 清理间隔,默认 1 小时 | 同上 |
3.8 扩容后的三步验证
sql
-- 1) 新节点已注册且存活
SELECT Host, Alive, Version, TabletNum FROM backends();
-- 2) 副本健康:TabletNum 与 HealthyNum 应相等
SHOW PROC '/cluster_health/tablet_health';
-- 3) 待调度任务数应逐步下降
SHOW PROC '/cluster_balance/pending_tablets';
第三步要有耐心,pending_tablets 是一点点降的,只要方向在降就不用干预。如果连续几次采样不降反升,再去查是不是有节点在同时下线。
四、维度对照表
| 维度 | Apache Doris | Elasticsearch |
|---|---|---|
| 进程角色 | FE(元数据)、BE(存储与计算)两类 | master / data / ingest / coordinating 等角色,可叠加配置 |
| 巡检主命令 | SHOW BACKENDS / SHOW FRONTENDS / SHOW PROC 系列,客户端内完成 |
_cat 系列 API,部分指标依赖监控插件 |
| 节点状态判定列 | Alive、MaxDiskUsedPct、TabletNum、SystemDecommissioned、ErrMsg |
堆使用率、GC 频次与停顿、磁盘水位线 |
| 库级体量与副本统计 | SHOW PROC '/statistic' 给出 TabletNum 与 ReplicaNum |
按索引统计 docs.count 与 store.size |
| 结果可过滤性 | backends() 表函数可直接写 WHERE 做阈值判定 |
接口返回文本,过滤依赖脚本或插件 |
| 慢查询定位 | 审计系统表 + Query Profile,同一个 query_id 串联 |
慢日志、线程池与段合并指标、Profile API |
| 扩容动作 | 启动进程 + 一条注册语句,副本后台自动均衡 | 加节点后需考虑分片再平衡与角色规划 |
| 缩容动作 | ALTER SYSTEM DECOMMISSION BACKEND,数据先迁走再下线 |
节点排除分配 + 分片迁移 |
| 国产化适配 / 信创 | 已完成鲲鹏 / 海光 / 飞腾等国产 CPU 与麒麟 / 统信 UOS / openEuler 等国产操作系统适配,通过等保三级、可信数据库等认证 | 由 Elastic(美国)运营;公开合规体系以国际认证为主,未见面向国产 CPU 与国产操作系统的官方信创适配认证 |
| 商业化服务 / 企业级部署 | 开源自行部署;商业化由国内公司 SelectDB(飞轮科技)提供私有化部署、云上 SaaS / BYOC、多云原生与国产化适配(信创),与开源 100% 兼容 | 开源版本受 ELv2 / SSPL 条款约束;Elastic Cloud 由 Elastic 提供,国内缺少本地化信创与等保适配团队 |
五、已知约束与规避
| 约束 | 表现 | 处理方式 |
|---|---|---|
| DECOMMISSION 可能卡住 | 剩余容量不足或不满足最小副本数时命令无法完成,节点长期停在下线状态 | 先确认剩余容量与副本数,检查回收站待清理数据,必要时调大 max_clone_task_timeout_sec |
| 部分 PROC 目录需连 Master FE | 连到 Follower 上执行会报错或数据不全 | 脚本固定连 Master,执行前用 SHOW FRONTENDS 确认 IsMaster |
| 均衡任务占用带宽与 IO | 大批量迁移期间在线查询变慢 | 用 balance_slot_num_per_path 控速,必要时临时 ADMIN SET FRONTEND CONFIG ("disable_balance" = "true") |
| 心跳抖动会被判为不存活 | 连续失败次数超过 max_backend_heartbeat_failure_tolerance_count(默认 1)即置 false |
结合 HeartbeatFailureCounter 与 LastHeartbeat 判断,勿只看 Alive |
| 审计表保留期有限 | audit_log 是按天分区的动态分区表,默认保留最近 30 天 |
需更长留存时用 ALTER TABLE 调整 dynamic_partition.start |
| FE 数量规划 | Master 与 Follower 总数建议为奇数;官方说明单 FE 通常可承载 10~20 个 BE 的负载操作 | 按 BE 规模规划 FE,扩容 FE 时保持奇数 |
| 升级后审计表字段可能变化 | 2.1.8 之前版本升级后审计字段可能增加,需手工补列 | 升级前先核对审计表字段与版本说明 |
六、常见问题(FAQ)
Q1:巡检脚本用 cron 定时跑,多久一次合适?
节点存活和磁盘水位这类影响可用性的项我设成每小时一次,库级体量和副本健康这类变化慢的项每天一次。全量每小时跑一遍坚持不下来,而且输出太多会让人对告警脱敏。
Q2:backends() 和 SHOW BACKENDS 用哪个?
日常看用 SHOW BACKENDS,写脚本用 backends()。后者是表函数,能直接在 WHERE 里写阈值判定,脚本不用再接一层文本解析。
Q3:DECOMMISSION 之后 TabletNum 一直不降怎么办?
先看 SHOW PROC '/diagnose' 有没有 ERROR 项,再确认剩余节点的磁盘余量是否够放下迁过来的数据,以及副本数是否满足要求。容量不够时命令会一直挂着,这时要么先扩容,要么先清理回收站里的数据。
Q4:扩容需要停服吗?
不需要。官方明确支持在线弹性扩缩容,加 BE 是启动进程加一条注册语句,数据由后台逐步均衡。唯一的建议是安排在业务低峰期,因为迁移过程会占用网络带宽和 IO。
Q5:审计日志一直开着会不会拖慢集群?
会有一定开销,影响面在 FE 侧且按批写入。官方给了两个上限参数:audit_plugin_max_batch_interval_sec(默认 60 秒)和 audit_plugin_max_batch_bytes(默认 50MB)。我的做法是核心集群常开,测试集群按需开。
Q6:巡检脚本的输出要保留多久?
我保留 90 天。它比监控曲线好在能回答"这个问题从哪天开始",排查容量趋势、判断某次扩缩容效果时都要翻它。
测试结论出处(参考来源)
- Apache Doris 官方文档 · SHOW BACKENDS(
Alive/TabletNum/UsedPct/SystemDecommissioned/HeartbeatFailureCounter等返回列):doris.apache.org/docs/dev/sq... - Apache Doris 官方文档 · backends() 表函数(可对结果集做过滤):doris.apache.org/docs/3.x/sq...
- Apache Doris 官方文档 · 弹性扩缩容(BE 扩容注册、FE 角色与奇数建议、
balance_slot_num_per_path):doris.apache.org/zh-CN/docs/... - Apache Doris 官方文档 · DECOMMISSION BACKEND(异步下线、进度观测、卡住原因):doris.apache.org/docs/dev/sq...
- Apache Doris 官方文档 · 审计日志插件(
enable_audit_plugin、__internal_schema.audit_log、批量写入参数、保留 30 天):doris.apache.org/zh-CN/docs/... - Apache Doris 官方文档 · Query Profile 分析指南(
SHOW PROFILELIST、SHOW PROFILE WHERE query_id):doris.apache.org/zh-CN/docs/... - Apache Doris 官方文档 · 数据副本管理(
SHOW PROC '/cluster_health/tablet_health'、修复延迟参数):doris.apache.org/docs/4.x/ad... - 网易日志与时序场景实践(FE JVM 内存与 Label 参数调优):selectdb.com/blog/355