第 24 关 · ★★★★★

可观测与故障诊断

Metrics、Profile、日志、Compaction 与 Tablet:做一次故障演练与复盘。

已点亮 · 最佳 分
可观测与故障诊断 第 1 页

Day 24|Apache Doris 可观测性与故障排查:Metrics、Grafana、Query Profile、日志与系统化诊断树

课程阶段: 第五阶段·生产环境与运维治理
建议学习时长: 3~4 小时
实验基线: Apache Doris 4.0.8 Stable / 4.1.3 Latest
今日目标: 建立一套从“发现异常”到“定位根因、验证修复、沉淀机制”的完整方法。

Day 24 全景
Day 24 全景

前二十三天,我们先后完成了 Doris 的定位、架构、表模型、导入、索引、物化视图、查询执行、存储引擎、事务更新、容量规划、高可用和工作负载治理。到了生产环境,真正考验团队的往往是另外一件事:系统发生抖动时,能否在有限时间里判断影响范围,找到可靠证据,完成止损,并把修复结果固化成长期机制。

很多故障都有相似的表象。经营大屏变慢,可能来自 SQL 扫描放大,也可能来自 Workload Group 排队、BE 磁盘延迟、Compaction 抢占、FE 规划变慢或外部 Catalog 抖动;导入延迟升高,可能来自 Kafka Lag、数据质量、事务发布、MemTable Flush、磁盘水位或副本异常。仅凭某一条报错或某一张 Grafana 曲线,很难得到稳定结论。

可观测性的价值,在于把系统运行时留下的外部信号组织成证据。Doris 提供 Metrics、日志、Audit、Query Profile、System Tables、Web 页面和 HTTP API;Linux 还提供 CPU、内存、磁盘与网络工具。运维工程师需要把这些能力串成一条有顺序的诊断链路。


一、可观测性要解决的四个问题

生产可观测体系至少要持续回答四个问题:

  1. 服务是否可用。 FE/BE 是否存活,查询与导入是否成功,数据是否按 SLA 更新。
  2. 性能是否稳定。 p50、p95、p99、排队时间、计划时间和执行时间是否偏离基线。
  3. 资源是否健康。 CPU、内存、磁盘、网络、线程池、Compaction、Tablet 与 Cache 是否进入饱和区。
  4. 异常能否解释。 能否通过 QueryID、Node、时间窗和变更编号,将 Metrics、日志、Profile 和系统状态关联起来。

四类证据
四类证据

可观测性建设需要避免“指标越多越好”的倾向。指标数量增长很快,维护成本、存储成本和告警噪声也会同步上升。更有效的做法是先确定服务目标,再选择能反映目标状态的信号,然后补齐根因定位所需的内部指标。

例如,一个面向经营大屏的集群,可以先定义:

  • 核心报表成功率;
  • p95 与 p99 响应时间;
  • 数据从业务事件发生到报表可见的端到端新鲜度;
  • 早高峰目标并发;
  • 关键 Workload Group 的排队比例;
  • 单节点故障时的服务降级范围。

围绕这些目标,继续补充 FE、BE、查询、存储和导入指标,体系会更加清晰。


二、Doris 可观测性的四类证据

2.1 Metrics:持续观察趋势与饱和度

Doris 的 FE 和 BE 都内置 Prometheus 兼容指标。FE 默认通过 HTTP 端口 8030 暴露,BE 默认通过 Web Server 端口 8040 暴露:

curl http://fe_host:8030/metrics
curl http://be_host:8040/metrics

# JSON 格式
curl 'http://fe_host:8030/metrics?type=json'
curl 'http://be_host:8040/metrics?type=json'

Metrics 适合回答“什么时候开始异常”“哪些节点偏离”“趋势是否持续”“资源是否达到瓶颈”。它能快速缩小时间窗和节点范围,却通常无法独立解释某一条 SQL 的内部行为。

2.2 Logs:记录事件、错误上下文和状态变化

日志适合回答“系统在异常时做了什么”“哪个组件返回了什么错误”“是否发生选主、崩溃、事务失败或副本修复”。FE 与 BE 的关键日志包括:

组件 日志 主要用途
FE fe.log 启动、元数据、调度、查询协调、一般运行信息
FE fe.warn.log WARN、ERROR、权限、RPC、异常状态
FE fe.audit.log Query、Slow Query、Load、Stream Load 审计
FE fe.out 标准输出、JVM 启动和崩溃信息
BE be.INFO 查询执行、内存、Tablet、Compaction、导入等运行信息
BE be.WARNING OOM 风险、IO、RPC、Tablet 和任务异常
BE be.out C++ Crash、标准输出与启动失败

2.3 Query Profile:观察一条查询真实执行了什么

Query Profile 记录单条查询在各个 BE 上的 Fragment、PipelineTask 和 Operator 指标。它能回答:

  • 哪个算子耗时最高;
  • 实际扫描了多少行和多少字节;
  • Runtime Filter 是否命中;
  • Join Build 侧是否过大;
  • Shuffle 发送与接收了多少数据;
  • 内存峰值和 Spill 发生在哪里;
  • 同一 Operator 在不同 Instance 上是否存在倾斜;
  • 主要时间花在计算还是依赖等待。

2.4 System Tables:用 SQL 查询运行状态

information_schema 中的系统表让运维数据可以直接用 SQL 聚合和关联。常用对象包括:

  • active_queries:FE 注册的运行查询;
  • backend_active_tasks:BE 正在执行的 Query、Load 等 Task;
  • workload_group_resource_usage:Workload Group 的 CPU、内存和扫描速率;
  • backend_tablets:Tablet 的 Version、Segment、Compaction Score 和大小;
  • rowsets:Rowset 版本、状态和存储信息;
  • routine_load_job:Routine Load 状态与任务信息;
  • processlist:连接和当前语句。

这四类证据通过时间、QueryID、节点 ID、Tablet ID、用户和 Workload Group 关联,形成完整诊断上下文。


三、搭建 Prometheus 与 Grafana 监控链路

监控架构
监控架构

一个典型链路由四层组成:

FE / BE / OS Metrics
        ↓
Prometheus 周期抓取与规则计算
        ↓
Grafana 看板与变更注释
        ↓
Alertmanager 路由、分组、抑制与通知

官方提供了两套 Grafana Dashboard:存算一体集群使用 shared-nothing 模板,存算分离集群使用 cloud 模板。生产落地时还需要补充操作系统指标。Doris 能看到进程内部状态,系统层工具能看到宿主机 CPU steal、磁盘 await、网络重传、文件系统水位等信息,两类视角相互补充。

3.1 Prometheus 抓取配置的关键点

监控配置的关键是标签设计和实例完整性,YAML 语法只承担配置表达:

  • 每个指标带有稳定的 clusterinstancerole 标签;
  • FE、BE 和存算分离组件使用统一集群标识;
  • 节点下线后保留一段时间序列,便于复盘;
  • 抓取间隔一般从 15~30 秒起步,高频告警指标可按需要缩短;
  • Prometheus 与 Doris 节点时间必须同步;
  • 监控服务器自身也要有容量、磁盘和抓取失败告警。

3.2 Counter 要转换成速率

官方指标表中大量指标属于 Counter,它们从进程启动后持续累加。直接看绝对值没有明确意义,常见处理方式是计算单位时间增量:

rate(doris_fe_query_total[5m])
rate(doris_fe_query_err[5m])
increase(doris_fe_query_err[10m])

错误率可以使用错误 Counter 的速率除以总请求 Counter 的速率。重启会导致 Counter 归零,Prometheus 的 rate() 能处理大多数正常重置场景。


四、指标体系:从 P0 到深度诊断

指标优先级
指标优先级

Apache Doris 官方指标文档为指标标注了优先级,P0 最高。生产建设可以分三步推进。

4.1 第一层:可用性与服务结果

这一层直接映射业务影响:

  • FE/BE Alive 与心跳;
  • 查询 QPS、成功数、错误数;
  • p50、p95、p99;
  • 当前运行、排队与拒绝的查询;
  • Stream Load、Routine Load、异步任务成功率;
  • 数据新鲜度;
  • 磁盘是否接近写保护阈值。

这组指标适合定义 P0/P1 告警和业务 SLO。

4.2 第二层:FE 健康

FE 指标地图
FE 指标地图

FE 承担连接接入、元数据、规划、事务协调和调度。重点观察:

  • JVM Heap 使用量、GC 次数和 GC 时间;
  • FE 是否存在 Master,Follower 是否同步;
  • EditLog / Journal 写入与回放;
  • RPC 队列和线程池;
  • 连接数、查询规划耗时和元数据规模;
  • 外部 Catalog 元数据缓存与刷新。

FE CPU 较高时,应先确认是高并发短查询造成规划压力,还是复杂 SQL 导致优化器搜索空间过大;JVM 内存持续升高时,要区分元数据、查询计划对象、外部 Catalog 缓存和异常引用。

4.3 第三层:BE 健康

BE 指标地图
BE 指标地图

BE 同时承担计算、存储、缓存、导入和 Compaction。重点观察:

  • CPU 使用率与负载;
  • BE 进程内存、系统可用内存、Jemalloc Cache;
  • Query、Load、Compaction 等 Memory Tracker;
  • 磁盘使用率、IOPS、吞吐、await 与错误;
  • 网络收发、RPC 延迟和重传;
  • 扫描字节、扫描行数和 Scanner 线程;
  • Tablet 数、Version 数、Segment 数和 Compaction Score;
  • 导入吞吐、Reject 行数与 Publish 延迟;
  • 线程池 Active、Queue 与拒绝。

4.4 第四层:查询与 Operator

查询层需要使用 Audit、Explain 和 Profile。宏观 Metrics 能说明集群整体负载,Profile 能把负载落到具体 Operator。二者结合后,才能判断一次 p99 上升属于系统资源不足,还是少数异常 SQL 放大资源消耗。


五、Grafana 看板如何设计得真正可用

Grafana 下钻路径
Grafana 下钻路径

一个完整 Dashboard 建议分成八个视角:

  1. 集群总览: FE/BE 存活、Master、容量、QPS、错误率;
  2. 查询性能: p50/p95/p99、运行数、排队数、超时和失败;
  3. FE 健康: JVM、GC、Journal、RPC、连接;
  4. BE 资源: CPU、内存、磁盘、网络;
  5. 执行与队列: Workload Group、线程池、等待与 Spill;
  6. 导入任务: Load 吞吐、Reject、Routine Lag、Publish;
  7. Tablet 与 Compaction: Version、Segment、Score、副本健康;
  8. 容量趋势: 数据增长、磁盘水位、Tablet 增长和未来预测。

看板还需要具备下钻能力。例如从 p99 折线跳转到同一时间窗的 FE/BE 资源面板,再跳转到慢 SQL 列表和 Profile。固定时间范围、节点变量、单位、颜色和告警状态能显著提高排障效率。

5.1 变更注释

很多异常都与变更相关。建议把以下事件写入 Grafana Annotation 或统一变更系统:

  • 应用发布;
  • SQL 或报表版本;
  • Doris 参数修改;
  • DDL、索引、物化视图和分区变更;
  • 扩缩容与节点重启;
  • Doris 升级;
  • 大规模补数、历史回灌和导入批次调整。

当指标异常起点与变更时间高度重合时,诊断可以快速收敛。


六、告警设计:症状、根因与降噪

告警需要同时覆盖用户症状和内部根因。

6.1 症状告警

  • 核心查询成功率下降;
  • p99 超出 SLO;
  • Routine Load Lag 超出数据新鲜度目标;
  • 关键报表或 API 连续失败;
  • 集群无法写入或无法选出 Master。

6.2 根因告警

  • FE JVM、Journal、RPC 队列异常;
  • BE CPU、内存、磁盘、网络饱和;
  • Compaction Score、Version Count 持续上升;
  • Workload Group 排队或拒绝增加;
  • Tablet 副本缺失或状态异常;
  • 外部 Catalog 元数据访问持续变慢。

6.3 降噪原则

  1. 对瞬时尖峰增加持续时间;
  2. 使用短窗口快速发现,长窗口确认持续性;
  3. 根因告警触发后抑制同一节点的派生告警;
  4. 按集群、节点、业务和事件分组;
  5. 维护窗口保留明确记录;
  6. 告警恢复时发送恢复通知;
  7. 每条告警包含 Runbook 和可直接打开的 Dashboard 链接。

阈值需要通过历史分位数和业务 SLO校准。单纯复制其他集群的阈值,容易产生大量误报或漏报。


七、Query Profile:从查询总览下钻到 PipelineTask

Profile 采集
Profile 采集

Profile 的核心组件包括 FE 的 ProfileManager 和 BE 的 AsyncReportThreadPool。查询开始时,执行 FE 注册 Profile;查询执行完成后,各 BE 将本地 Profile 作为异步任务上报;FE 聚合、保留和淘汰 Profile,也可以将适合持久化的 Profile 压缩写入本地目录。

7.1 当前关键参数

参数 默认值 作用
enable_profile false 是否生成 Profile
profile_level 1 4.0+ 的 Profile 详细程度,范围 1~3
auto_profile_threshold_ms -1 仅为超过阈值的查询生成 Profile
max_query_profile_num 500 FE 内存中最多保留的 Profile 数
max_spilled_profile_num 500 磁盘最多保留的 Profile 数
spilled_profile_storage_path log/profile Profile 本地存储目录
spilled_profile_storage_limit_bytes 1 GB 磁盘 Profile 总容量上限

实验环境可以使用:

SET enable_profile = true;
SET profile_level = 2;
SET auto_profile_threshold_ms = 1;

生产环境更适合设置慢查询阈值,只保留真正需要分析的 Query,避免 Profile 本身增加 FE/BE 开销和存储压力。

7.2 Profile 五部分阅读顺序

Profile 阅读指南
Profile 阅读指南

  1. Summary: 确认 QueryID、总耗时、状态、用户和时间;
  2. ExecutionSummary: 判断 Planner、Fragment 调度和执行阶段的时间;
  3. ChangedSessionVariables: 检查查询是否修改了内存、并行度、超时、Runtime Filter 等参数;
  4. MergedProfile: 找出最慢 Operator,观察 InputRows、RowsProduced、ExecTime、WaitForDependency 和 min/avg/max;
  5. DetailProfile: 下钻到特定 BE、Instance 和 PipelineTask。

7.3 先看等待,再看计算

Operator 的 ExecTime 表示自身执行耗时,WaitForDependency 表示等待依赖条件的时间。一个 Exchange Operator 看起来耗时很长,真实原因可能是上游 Join、Sort 或网络迟迟没有数据到达。诊断时需要沿等待链向上游追踪。

7.4 用 min/avg/max 识别数据倾斜

MergedProfile 会聚合同一 Operator 在多个 Instance 上的指标。当 max 远高于 avg,或 min=0max 很大时,通常需要检查分桶不均、热点 Key、Join Key 中大量 NULL、单个大文件或 Tablet 倾斜。

7.5 常见 Operator 观察点

Operator 重点指标 解释方向
Scan ScanRows、ScanBytes、FilteredRows、IOTime 分区/Tablet/Page 裁剪、索引、列裁剪、磁盘或远端 IO
Hash Join BuildRows、HashTable、PeakMemory、Wait Build 侧大小、Distribution、Runtime Filter、倾斜
Exchange BytesSent/Received、WaitForData Shuffle 规模、网络、上下游阻塞
Aggregate InputRows、HashTable、PeakMemory、Spill 分组基数、局部聚合、内存预算
Sort / TopN InputRows、PeakMemory、SpillBytes 排序范围、TopN 下推、落盘

八、日志、Audit 与慢查询

日志关联
日志关联

官方 FE 日志当前默认按 age 保留:fe.logfe.warn.log 默认 7 天,fe.audit.log 默认 30 天。Audit 模块默认包含 slow_queryqueryloadstream_loadqe_slow_log_ms 默认 5000 ms。

8.1 Audit Log 中要关注什么

Audit Log 适合做历史分析,常用字段通常包括:

  • QueryID、用户、客户端 IP;
  • Catalog、Database;
  • SQL、SQL Digest;
  • 开始时间、总耗时、状态;
  • 扫描行数与字节;
  • CPU Time;
  • Peak Memory;
  • Workload Group;
  • 返回行数与错误信息。

SQL Digest 能把参数不同、结构相同的 SQL 聚合到一起,便于识别某类 SQL 的总资源消耗。只按单次最大耗时排序,容易忽略高频中等成本 SQL 的累计影响。

8.2 日志搜索方法

日志搜索建议固定几个关联键:

时间窗
QueryID
Connection ID
User / IP
Tablet ID / Backend ID
Label / Transaction ID

面对 BE 内存问题,可以先从 be.INFO 中的 Memory Tracker Summary 找到 QueryID,再回到 fe.audit.log 获取 SQL,随后获取 Explain 和 Profile。面对加载失败,先读 Stream Load 返回 JSON 和 Error URL,再查询 Label 与事务状态。

8.3 日志采集的工程要求

  • 使用 Vector、Filebeat 或同类采集器集中汇聚;
  • 保留原始时间戳、节点、文件名和日志级别;
  • 多行堆栈需要正确合并;
  • 查询 SQL 和用户信息需要权限控制;
  • K8s 环境要明确 stdout 与持久卷日志的采集方式;
  • DEBUG 只针对目标类或包短时开启,完成后立即恢复。

登录后可阅读本文完整内容。