Apache Doris 副本故障排查与修复实战指南

前言
在使用 Apache Doris 作为时序数据存储时,生产环境偶发以下报错:
java.sql.SQLException: errCode = 2, detailMessage = Failed to get scan range,
no queryable replica found in tablet: 8935003.
Reason: Visible Replicas:Visible version: 53409,
Replicas: [replicaId=8935004, backendId=10004, backendAlive=true,
version=53409, lastFailedVersion=53410, lastSuccessVersion=53409,
lastFailedTimestamp=1773297614783, state=NORMAL]
本文系统梳理该报错的根因分析、排查流程与修复方案。
一、错误解读
拆解错误信息中的关键字段:
| 字段 | 值 | 含义 |
|---|---|---|
tablet |
8935003 | 问题 Tablet ID |
backendAlive |
true | BE 节点存活 |
version |
53409 | 副本当前版本 |
lastSuccessVersion |
53409 | 最后一次成功同步版本 |
lastFailedVersion |
53410 | 在 53410 版本同步失败 |
lastFailedTimestamp |
1773297614783 | 失败时间戳 |
state |
NORMAL | 副本状态标记为正常 |
核心矛盾:
version == lastSuccessVersion < lastFailedVersion
副本在版本 53410 的数据写入失败,且未能自动修复。虽然 backendAlive=true、state=NORMAL,但 Doris FE 判定该副本不可查询,导致整个 Tablet 无可用副本,查询直接报错。
二、根因分析
2.1 常见触发场景
数据写入 → Tablet 53410 版本刷盘 → BE 磁盘 IO 异常 / 内存不足
→ Compaction 失败
→ 网络抖动导致副本同步中断
→ BE 进程重启,WAL 未完整回放
2.2 副本版本落后的影响链
lastFailedVersion > version
↓
FE 标记副本不可查询(non-queryable)
↓
Tablet 无 queryable replica
↓
查询报 "no queryable replica found"
↓
业务查询全部失败
2.3 为何 ADMIN REPAIR 不一定立即生效
Doris 的副本修复依赖后台 TabletChecker 线程周期性扫描,默认检查间隔为 5 分钟。触发修复后需等待:
- FE 检测到副本异常
- 生成 Clone 任务,从健康副本复制数据
- 版本追平,重新标记为 queryable
三、排查流程
Step 1:定位问题 Tablet 详情
sql
-- 查看 Tablet 所在表、分区、副本详情
SHOW TABLET 8935003;
返回结果关注:
DbName/TableName/PartitionName--- 定位问题范围State--- 副本状态LstFailedVer--- 失败版本号
Step 2:检查 BE 节点状态
sql
-- 查看所有 BE 节点健康状态
SHOW BACKENDS;
重点关注:
Alive是否为 trueTabletNum是否异常偏高LastStartTime--- 是否近期有重启
Step 3:检查表的副本分布
sql
-- 查看表的 Tablet 整体状态
SHOW TABLET FROM huazhiqiao_db.plc_point_data;
-- 过滤出不健康副本
SELECT * FROM information_schema.tablets
WHERE TABLE_NAME = 'plc_point_data'
AND tablet_state != 'NORMAL';
Step 4:查看 FE/BE 日志
bash
# FE 日志 --- 查找副本修复相关
grep "8935003\|TabletChecker\|replica.*failed" fe/log/fe.log | tail -50
# BE 日志 --- 查找 Compaction / IO 错误
grep "8935003\|compaction.*failed\|disk.*error" be/log/be.WARNING | tail -50
四、修复方案
方案一:触发系统自动修复(推荐首选)
sql
-- 触发 FE 对指定表分区的副本修复
ADMIN REPAIR TABLE huazhiqiao_db.plc_point_data
PARTITION p20250511;
-- 5 分钟后验证副本是否追平
SHOW TABLET 8935003;
-- 期望:lastFailedVersion = -1,version 追上最新
方案二:删除损坏分区(数据可丢弃时)
适用于时序场景下历史分区数据已过期、无需保留的情况。
sql
-- Step 1:关闭动态分区(防止操作期间自动建分区干扰)
ALTER TABLE huazhiqiao_db.plc_point_data
SET ("dynamic_partition.enable" = "false");
-- Step 2:确认分区名称
SHOW PARTITIONS FROM huazhiqiao_db.plc_point_data;
-- Step 3:删除问题分区
ALTER TABLE huazhiqiao_db.plc_point_data
DROP PARTITION p20250511;
-- Step 4:重新启用动态分区
ALTER TABLE huazhiqiao_db.plc_point_data
SET ("dynamic_partition.enable" = "true");
方案三:删除前先备份(数据需保留时)
sql
-- Step 1:备份问题分区数据
CREATE TABLE plc_point_data_backup_p20250511
AS SELECT * FROM huazhiqiao_db.plc_point_data
PARTITION (p20250511);
-- Step 2:确认备份行数
SELECT COUNT(*) FROM plc_point_data_backup_p20250511;
-- Step 3:再执行方案二的删除流程
方案四:手动设置副本状态(高级操作,谨慎使用)
sql
-- 将问题副本标记为 bad,触发重新 Clone
ADMIN SET REPLICA STATUS
PROPERTIES(
"tablet_id" = "8935003",
"backend_id" = "10004",
"status" = "bad"
);
注意: 此操作会触发副本重建,期间该副本不可用,确保集群有其他健康副本再执行。
五、修复验证
sql
-- 1. 检查 Tablet 副本版本是否追平
SHOW TABLET 8935003;
-- 期望:lastFailedVersion = -1
-- 2. 检查表查询是否恢复
SELECT COUNT(*)
FROM huazhiqiao_db.plc_point_data
WHERE ts >= '2025-05-11 00:00:00'
AND ts < '2025-05-12 00:00:00';
-- 3. 查看集群整体不健康 Tablet 数量
SHOW PROC '/statistic';
-- 关注 UnhealthyTabletNum 是否归零
六、预防措施
6.1 动态分区合理配置
针对时序场景,建议限制历史分区保留数量,避免分区过多导致 Tablet 数量膨胀:
sql
ALTER TABLE huazhiqiao_db.plc_point_data SET (
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-30", -- 保留近 30 天
"dynamic_partition.end" = "3", -- 提前建 3 天
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "8",
"dynamic_partition.replication_num" = "3" -- 3 副本保障可用性
);
6.2 副本数建议
| 场景 | 推荐副本数 | 原因 |
|---|---|---|
| 生产时序数据 | 3 | 允许 1 副本故障仍可读写 |
| 历史冷数据 | 2 | 降低存储成本 |
| 单机测试 | 1 | 节省资源 |
6.3 监控告警配置
建议对以下指标配置告警:
sql
-- 定期巡检不健康 Tablet
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COUNT(*) AS unhealthy_tablet_count
FROM information_schema.tablets
WHERE tablet_state != 'NORMAL'
GROUP BY TABLE_SCHEMA, TABLE_NAME
HAVING COUNT(*) > 0;
将上述 SQL 接入定时任务(如每 10 分钟执行一次),发现 unhealthy_tablet_count > 0 立即告警。
七、总结
| 场景 | 推荐方案 |
|---|---|
| 单个 Tablet 版本落后,BE 存活 | ADMIN REPAIR TABLE + 等待自动修复 |
| 时序历史分区,数据已过期 | 直接 DROP PARTITION |
| 数据需保留,分区异常 | 备份后删除分区,重新导入 |
| 多副本均异常,BE 磁盘故障 | 先修复 BE,再触发副本修复 |
| 紧急恢复查询可用性 | 临时降低副本要求 + 删除异常分区 |
核心结论:
lastFailedVersion > lastSuccessVersion是 Doris 副本不可查询的直接原因。优先通过ADMIN REPAIR触发自动修复;时序场景下过期分区可直接删除,以最低成本恢复服务。