doris各服务器存储不均匀,导致BE节点不稳定

在 Doris 场景里通常有以下几类原因

🧩 一、存储不均匀的常见原因与解决方案

① 分桶(buckets)不合理

  • 问题:分桶字段选择不当,导致某些值的数据量特别大(例如按 acct_day 分桶,而某几天数据特别多)。

  • 现象:部分 BE 存储占用 80%+,其他仅 20%。

  • 解决方案:

    • 检查表的分桶方式:

      SHOW CREATE TABLE db.table_name;
      

      优化:

    • 若当前是 DISTRIBUTED BY HASH(acct_day) BUCKETS 4,建议改为业务层分布更均衡的字段,例如 HASH(device_id)HASH(user_id)

    • 若使用聚合模型(Aggregate Key),可适度增加 BUCKET 数量(如 16、32、64),再重新导入数据(可使用 INSERT INTO new_table SELECT * FROM old_table)。

② Tablet(分片)迁移未完成或失衡

  • Doris 会自动平衡 Tablet,但如果:

    • 某些 BE 容量已接近满;

    • 集群负载高;

    • tablet_scheduler 参数太保守;
      则迁移可能停滞。

    • 排查:

      SHOW PROC '/cluster_balance';
      

      或查看:

      SHOW PROC '/backends';
      

字段含义详解

字段含义当前值解读
cluster_load_stat当前集群的负载状态(0 表示空闲,1 表示正在调度)1 → 正在执行负载均衡任务(Tablet 迁移中)
working_slots当前正在执行的平衡任务数量(并发调度线程数)6 → 表示目前有 6 个平衡任务同时运行,调度压力较大
sched_stat调度状态(0 表示正常,>0 表示异常)0 → 调度模块工作正常 ✅
priority_repair高优先级修复任务数量(比如副本缺失、损坏)0 → 当前没有损坏副本任务 ✅
pending_tablets待调度的 Tablet 数量(待迁移、待修复)1 → 仅剩 1 个 Tablet 待调度,说明几乎完成均衡 ✅
running_tablets当前正在迁移的 Tablet 数量0 → 目前没有迁移任务正在执行,可能刚完成一次调度 ✅
history_tablets历史上调度过的 Tablet 数量1000 → 表示曾经平衡过 1000 个 Tablet(正常)

输出看:

✅ 集群调度器是 健康的,没有出现调度挂死或异常;
⚙️ 系统刚刚或正在进行 少量 rebalance 操作
⚠️ 但这并不能解释 “存储不均匀 + BE 节点频繁挂” 的根因。

因为这条命令只反映 调度状态,还需要结合 SHOW PROC '/backends'; 才能看出:

  • 哪个 BE 存储量明显过高;

  • 哪个 BE 经常掉线;

  • 数据分布是否极度倾斜。

分析:

  • 哪些节点磁盘占用高(例如 85%+);

  • 哪些节点频繁掉线(Alive=false);

  • 是否存在严重的 tablet 不均衡(TabletNum 差异很大);

  • 是否需要手动触发 rebalance 或重新分桶建表。


🧠 二、主要问题诊断
✅ 1. Tablet 分布极不均衡
  • Tablet 数量差距:从 1,821 → 29,020,差距约 16 倍

  • 这说明 数据分桶非常不均匀,自动平衡也没能完全修复。

📍可能原因:

  • 分桶字段选得不合理(例如按 acct_day 或某个低基数字段分桶)。

  • 建表时部分 BE 未加入集群或容量不同,导致 Tablet 初始分配倾斜。

  • 历史上有节点挂过,自动迁移导致 Tablet 聚集。


⚠️ 2. 磁盘空间差异过大
  • 173.11 只有 390GB 总容量,而其他节点是 1TB。
    这说明你的节点硬件 容量不一致
    Doris 默认 不感知磁盘大小差异,会尝试“均分 Tablet 数量”,不是“均分容量”。
    因此小盘节点(173.11、173.13)很容易被写满,最终导致挂掉。

📍典型结果:

  • 小盘节点 compaction 时 I/O 压力大;

  • WAL 或 tmp 目录撑爆 → BE 进程崩溃;

  • FE 检测到挂点后触发副本迁移,形成恶性循环。


⚙️ 3. 部分 BE compaction 压力过高
  • 173.16 Tablet 量最高(29k),磁盘占用高(67%);

  • 这类节点 compaction 线程持续占用 CPU 与 IO。

📍验证方法:

SHOW PROC '/compactions';

running 持续较多或某些表 compaction backlog 高,说明瓶颈在这里。

⚙️ 二、BE 节点频繁宕机的原因与排查

① 内存不足或 OOM

  • 现象:BE 日志(be.INFO)中出现:

    Memory limit exceeded
    killed by OOM killer
    
  • 排查:

    grep -i "oom" be.INFO
    dmesg | grep -i kill
    
    
    
    # 1. 检查系统是否因 OOM Killer 杀掉 BE
    sudo dmesg | grep -i "killed process"
    
    # 2. 检查 BE 是否报内存分配错误
    grep -iE "Out of memory|std::bad_alloc|Cannot allocate memory" /data/doris/be/log/be.INFO*
    
    # 3. 查看 BE 当前的内存使用率
    curl http://127.0.0.1:8040/api/metrics | grep memory
    
    
    # 4.更精准地检测 Doris BE 是否出现 OOM
    grep -iE "Out of memory|Killed process|Cannot allocate memory|std::bad_alloc" be.INFO be.WARNING be.ERROR
    
  • 优化方案:

  • 调整内存限制(be.conf):

    mem_limit = 70%
    

    若是查询或导入高峰导致,建议使用 查询并发控制

    SET global exec_mem_limit=4G;
    

    ② 磁盘 I/O 异常

  • 问题:Doris BE 写入磁盘压力大(特别是 Compaction 阶段)。

  • 排查:

    iostat -x 1 10
    

    查看是否存在单盘 %util 长时间 100%。

  • 优化方案:

    • 增加磁盘或采用 RAID10;

  • 调整 Compaction 参数:

    disable_auto_compaction = true
    

    然后手动触发:

    SHOW PROC '/compactions';
    

③ 网络波动或心跳超时

  • 现象fe.warn.log 出现:

    backend heartbeat timeout
    
  • 原因:FE <-> BE 心跳包延迟超时(默认 5s)。

  • 优化:

    • 网络带宽 >= 10Gbps;

  • fe.conf 调整:

    heartbeat_interval_second = 10
    

④ Doris 版本 bug 或存储引擎问题

  • 某些 Doris 版本(尤其是 1.2.x 早期)存在 TabletMeta 或 Compaction 崩溃 bug。

  • 建议:

    • 升级至 Apache Doris 2.1+(推荐 2.1.6 或更高)

    • 并执行:

      ADMIN SHOW FRONTENDS;
      ADMIN SHOW BACKENDS;
      

🔧 三、建议的诊断命令组合

目标命令
查看节点状态SHOW PROC '/backends';
查看负载均衡情况SHOW PROC '/cluster_balance';
查看磁盘使用SHOW PROC '/disks';
查看 Compaction 状态SHOW PROC '/compactions';
查看内存情况curl http://BE_IP:8040/api/show_proc?path=/mem_tracker

🧠 四、自动检测脚本的实现

自动检测 Doris 集群负载不均衡 的 SQL 脚本,用来定时监控(比如通过 Crontab 执行),如果发现有节点存储使用率过高或 Tablet 分布过于倾斜,就触发报警(例如打印告警信息或写入日志表)

🧩 一、核心思路

监控的关键指标来自:

SHOW PROC '/backends';

我们只需要从中提取以下列进行分析:

  • Host

  • TabletNum

  • CapacityUsedPct

  • Alive

  • DataUsedCapacity

  • TotalCapacity

然后计算:

  1. 存储占用方差(判断空间不均)

  2. Tablet 数量方差(判断分片不均)

  3. 离线节点(Alive = false)

一旦满足如下任意条件,即触发报警:

条件含义
max(CapacityUsedPct) - min(CapacityUsedPct) > 30存储空间差距超过 30%
max(TabletNum) / min(TabletNum) > 3tablet 分布差距超过 3 倍
存在 Alive = false 节点节点掉线
max(CapacityUsedPct) > 85某节点磁盘使用超过 85%

🧠 二、SQL 检测脚本(适合在 FE 控制台或定时任务中执行)

-- Doris 集群节点负载检测脚本
-- 执行方式:在 FE 上运行,或用 MySQL 客户端连接执行
-- 建议配合 cron 每隔 30 分钟执行一次

WITH backend_stats AS (
    SELECT
        BackendId,
        Host,
        Alive,
        TabletNum,
        CAST(SPLIT_PART(CapacityUsedPct, ' ', 1) AS DOUBLE) AS used_pct
    FROM
        (SHOW PROC '/backends')
)
SELECT
    NOW() AS check_time,
    COUNT(*) AS total_nodes,
    SUM(CASE WHEN Alive = 'true' THEN 1 ELSE 0 END) AS alive_nodes,
    ROUND(MAX(used_pct) - MIN(used_pct), 2) AS capacity_diff,
    ROUND(MAX(used_pct), 2) AS max_used_pct,
    ROUND(MIN(used_pct), 2) AS min_used_pct,
    ROUND(MAX(TabletNum) / GREATEST(MIN(TabletNum), 1), 2) AS tablet_ratio,
    CASE
        WHEN SUM(CASE WHEN Alive = 'false' THEN 1 ELSE 0 END) > 0 THEN '❌ 有节点掉线'
        WHEN MAX(used_pct) > 85 THEN '⚠️ 磁盘占用过高'
        WHEN (MAX(used_pct) - MIN(used_pct)) > 30 THEN '⚠️ 存储分布不均'
        WHEN (MAX(TabletNum) / GREATEST(MIN(TabletNum), 1)) > 3 THEN '⚠️ Tablet 分布不均'
        ELSE '✅ 集群负载均衡正常'
    END AS status_desc
FROM backend_stats;

🧾 示例输出:

| check_time          | total_nodes | alive_nodes | capacity_diff | max_used_pct | tablet_ratio | status_desc    |
| ------------------- | ----------- | ----------- | ------------- | ------------ | ------------ | -------------- |
| 2025-10-11 10:20:00 | 6           | 6           | 34.64         | 75.08        | 15.93        | ⚠️ Tablet 分布不均 |

🔧 三、自动报警思路(扩展)

你可以:

  1. 在 Doris 里建一个日志表 保存每次检测结果;

  2. 用外部脚本(如 Shell/Python)读取结果,检测到 “⚠️ 或 ❌” 自动发邮件/钉钉消息。

例:创建日志表
CREATE TABLE IF NOT EXISTS monitor.doris_balance_log (
    check_time DATETIME,
    total_nodes INT,
    alive_nodes INT,
    capacity_diff DOUBLE,
    max_used_pct DOUBLE,
    min_used_pct DOUBLE,
    tablet_ratio DOUBLE,
    status_desc VARCHAR(100)
) ENGINE=OLAP
DUPLICATE KEY(check_time)
DISTRIBUTED BY HASH(check_time) BUCKETS 1
PROPERTIES("replication_num"="1");

插入检测结果

INSERT INTO monitor.doris_balance_log
WITH backend_stats AS (
    SELECT
        BackendId,
        Host,
        Alive,
        TabletNum,
        CAST(SPLIT_PART(CapacityUsedPct, ' ', 1) AS DOUBLE) AS used_pct
    FROM
        (SHOW PROC '/backends')
)
SELECT
    NOW(),
    COUNT(*),
    SUM(CASE WHEN Alive = 'true' THEN 1 ELSE 0 END),
    ROUND(MAX(used_pct) - MIN(used_pct), 2),
    ROUND(MAX(used_pct), 2),
    ROUND(MIN(used_pct), 2),
    ROUND(MAX(TabletNum) / GREATEST(MIN(TabletNum), 1), 2),
    CASE
        WHEN SUM(CASE WHEN Alive = 'false' THEN 1 ELSE 0 END) > 0 THEN '❌ 有节点掉线'
        WHEN MAX(used_pct) > 85 THEN '⚠️ 磁盘占用过高'
        WHEN (MAX(used_pct) - MIN(used_pct)) > 30 THEN '⚠️ 存储分布不均'
        WHEN (MAX(TabletNum) / GREATEST(MIN(TabletNum), 1)) > 3 THEN '⚠️ Tablet 分布不均'
        ELSE '✅ 集群负载均衡正常'
    END
FROM backend_stats;

🕒 四、自动化执行(推荐方式)

Linux 定时任务(crontab)
*/30 * * * * mysql -h fe_host -P9030 -uroot -p'password' -Dmonitor \
  -e "INSERT INTO monitor.doris_balance_log ... (上面的SQL脚本)"

再结合公司的数据库,将告警发送到手机上

 五、Doris BE 集群自动监控脚本

功能目标

  1. 检测每个 BE 节点的 磁盘使用率内存使用率

  2. 扫描 BE 日志是否有 OOM / 内存分配失败

  3. 生成报警信息(打印在终端或写入日志文件)

  4. 可选:发送邮件或钉钉通知(可扩展)

脚本示例(Shell + curl + grep)

保存为 doris_be_monitor.sh 并给执行权限 chmod +x doris_be_monitor.sh

#!/bin/bash

##############################################
# Doris BE 自动监控脚本
# 功能:
# 1. 检测每个 BE 节点磁盘/内存使用率
# 2. 扫描 OOM 错误
# 3. 打印报警日志,可扩展邮件/钉钉告警
##############################################

# 配置区
FE_HOST="fe_host_ip"        # FE 地址
FE_PORT=9030                # FE SQL端口
BE_LIST=("173.11" "173.12" "173.13" "173.14" "173.15" "173.16") # 所有 BE IP
BE_WEB_PORT=8040            # BE Web 端口
LOG_DIR="/home/doris/monitor_logs"
MAIL_TO="ops@example.com"   # 邮件收件人
THRESHOLD_CAPACITY=85       # 磁盘使用率报警阈值 %
THRESHOLD_MEM=85            # 内存使用率报警阈值 %

mkdir -p $LOG_DIR
LOG_FILE="$LOG_DIR/doris_be_monitor_$(date +%F).log"

echo "================ Doris BE Monitor Start $(date) ================" | tee -a $LOG_FILE

# 1. 获取各 BE 磁盘和内存使用率
echo ">> 检查 BE 磁盘和内存使用率" | tee -a $LOG_FILE
for BE in "${BE_LIST[@]}"; do
    METRICS=$(curl -s http://$BE:$BE_WEB_PORT/api/metrics)
    # 提取磁盘占用百分比
    DISK_USED=$(echo "$METRICS" | grep 'disk_usage' | awk '{print $2}')
    MEM_USED=$(echo "$METRICS" | grep 'process_resident_memory_bytes' | awk '{printf "%.0f\n",$2/1024/1024/1024}') # GB
    MEM_TOTAL=$(echo "$METRICS" | grep 'mem_limit' | awk '{printf "%.0f\n",$2/1024/1024/1024}') # GB
    MEM_PCT=$(( MEM_USED*100 / MEM_TOTAL ))

    ALERTS=""
    if [ "$DISK_USED" -ge "$THRESHOLD_CAPACITY" ]; then
        ALERTS+="⚠️ 磁盘使用过高 "
    fi
    if [ "$MEM_PCT" -ge "$THRESHOLD_MEM" ]; then
        ALERTS+="⚠️ 内存使用过高 "
    fi

    echo "BE $BE | DiskUsed=$DISK_USED% | MemUsed=$MEM_PCT% | $ALERTS" | tee -a $LOG_FILE
done

# 2. 扫描 OOM 错误
echo ">> 扫描 BE 日志 OOM 错误" | tee -a $LOG_FILE
for BE in "${BE_LIST[@]}"; do
    BE_LOG_DIR="/data/doris/be/log"  # 如果 BE 日志路径不同,请修改
    OOM_COUNT=$(grep -iE "Out of memory|Killed process|Cannot allocate memory|std::bad_alloc" $BE_LOG_DIR/be.INFO* | wc -l)
    if [ "$OOM_COUNT" -gt 0 ]; then
        echo "❌ BE $BE 发现 $OOM_COUNT 条 OOM / 内存错误!" | tee -a $LOG_FILE
    else
        echo "BE $BE 无 OOM 错误" | tee -a $LOG_FILE
    fi
done

# 3. 可选:邮件告警
ALERT_FLAG=$(grep -E "⚠️|❌" $LOG_FILE)
if [ ! -z "$ALERT_FLAG" ]; then
    echo -e "$ALERT_FLAG" | mail -s "[Doris BE Monitor] 警报 $(date)" $MAIL_TO
fi

echo "================ Doris BE Monitor End $(date) ================" | tee -a $LOG_FILE

🔹 使用方法

  1. 将脚本保存到 Doris FE 或管理服务器

  2. 配置:

    • BE_LIST → 所有 BE IP

    • BE_LOG_DIR → BE 日志路径

    • MAIL_TO → 告警邮箱

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值