news 2026/6/10 17:26:21

【源码分析】StarRocks 初始化场景:Follower FE 找不到 BE 导致 “Cluster has no available capacity“ 问题分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【源码分析】StarRocks 初始化场景:Follower FE 找不到 BE 导致 “Cluster has no available capacity“ 问题分析

文章目录

    • 问题场景
    • 根本原因分析
      • 1. BE 注册机制
      • 2. 问题发生的时序
      • 3. 代码流程分析
        • 3.1 BE 注册到 Leader FE
        • 3.2 Follower FE 同步 BE 信息
        • 3.3 容量检查逻辑
    • 为什么会出现这个问题?
      • 原因1:Follower 启动/同步延迟
      • 原因2:Follower 的 journal replay 卡住
      • 原因3:BE 注册时 Follower 还没完全加入集群
    • 解决方案
      • 方案1:等待 Follower 同步完成(推荐)
      • 方案2:重启 Follower FE(如果同步卡住)
    • 预防措施
      • 1. 正确的启动顺序
      • 2. 监控 Follower 同步状态
      • 3. 确保网络连通性
    • 代码关键点总结
    • 快速诊断命令
    • 总结

问题场景

初始化流程

  1. 先启动 3 个 FE(1 Leader + 2 Follower)
  2. 然后启动 3 个 BE(BE 通过 MySQL 连接到 FE 并注册自己)

问题现象

  • 两个 Follower FE 报错:Cluster has no available capacity
  • Leader FE 可能正常(能看到 BE)

根本原因分析

1. BE 注册机制

BE 启动时,会通过MySQL 协议连接到 FE 并注册自己。关键点:

  • BE 只连接到指定的 FE(通常是 Leader,或配置的 helper FE)
  • BE 注册操作只在连接的 FE 上执行,不会直接广播到所有 FE
  • BE 注册信息通过 EditLog 同步到其他 FE

2. 问题发生的时序

时间线: T1: 启动 3 个 FE - FE1 成为 Leader - FE2, FE3 成为 Follower(可能还在同步 journal) T2: 启动 3 个 BE - BE1 连接到 Leader FE1,注册成功 - BE2 连接到 Leader FE1,注册成功 - BE3 连接到 Leader FE1,注册成功 Leader FE1: - 执行 addBackend() → 更新 idToBackendRef - 记录到 EditLog: logAddBackend() - 此时 Leader 能看到 3 个 BE,容量正常 T3: Follower FE2, FE3 的状态 - 如果 Follower 还没完全启动/同步完成 - 或者 Follower 的 journal replay 还没追上 - 它们可能还没 replay 到 BE 注册的 EditLog - 因此 idToBackendRef 还是空的(或只有部分 BE) - 导致 getClusterAvailableCapacityB() 返回 0 或很小 - 触发 "Cluster has no available capacity" 错误

3. 代码流程分析

3.1 BE 注册到 Leader FE

当 BE 通过 MySQL 连接到 Leader FE 并执行注册时:

// SystemInfoService.addBackend() 方法(第 203-224 行)privatevoidaddBackend(Stringhost,intheartbeatPort){BackendnewBackend=newBackend(GlobalStateMgr.getCurrentState().getNextId(),host,heartbeatPort);// 1. 更新 Leader 的 idToBackendRef(立即生效)Map<Long,Backend>copiedBackends=Maps.newHashMap(idToBackendRef);copiedBackends.put(newBackend.getId(),newBackend);idToBackendRef=ImmutableMap.copyOf(copiedBackends);// 2. 记录到 EditLog(用于同步到 Follower)GlobalStateMgr.getCurrentState().getEditLog().logAddBackend(newBackend);LOG.info("finished to add {} ",newBackend);}

关键点

  • Leader 的idToBackendRef立即更新(Leader 能立即看到 BE)
  • BE 注册信息记录到 EditLog(需要时间同步到 Follower)
3.2 Follower FE 同步 BE 信息

Follower FE 通过Replay EditLog来同步 BE 信息:

// SystemInfoService.replayAddBackend() 方法(第 909-934 行)publicvoidreplayAddBackend(BackendnewBackend){// 更新 Follower 的 idToBackendRefMap<Long,Backend>copiedBackends=Maps.newHashMap(idToBackendRef);copiedBackends.put(newBackend.getId(),newBackend);idToBackendRef=ImmutableMap.copyOf(copiedBackendRef);// 添加到集群if(newBackend.getBackendState()==BackendState.using){finalClustercluster=GlobalStateMgr.getCurrentState().getCluster();if(null!=cluster){cluster.addBackend(newBackend.getId());}}}

关键点

  • Follower 的idToBackendRef只有在 Replay EditLog 时才会更新
  • 如果 Follower 的 journal replay还没追上,就看不到新注册的 BE
3.3 容量检查逻辑

当 TableKeeper 或其他组件尝试创建表时:

// SystemInfoService.checkClusterCapacity() 方法(第 1024-1028 行)publicvoidcheckClusterCapacity()throwsDdlException{if(getClusterAvailableCapacityB()<=0L){thrownewDdlException("Cluster has no available capacity");}}// SystemInfoService.getClusterAvailableCapacityB() 方法(第 1007-1022 行)publiclonggetClusterAvailableCapacityB(){List<Backend>clusterBackends=getBackends();// 从 idToBackendRef 获取longcapacity=0L;for(Backendbackend:clusterBackends){if(backend.isDecommissioned()){capacity-=backend.getDataUsedCapacityB();}else{capacity+=backend.getAvailableCapacityB();// 如果 BE 不在 idToBackendRef 中,这里就是 0}}returncapacity;}

关键点

  • getBackends()idToBackendRef获取 BE 列表
  • 如果 Follower 的idToBackendRef还是空的(或只有部分 BE),容量就是 0
  • 触发 “Cluster has no available capacity” 错误

为什么会出现这个问题?

原因1:Follower 启动/同步延迟

场景

  • Follower FE2, FE3 启动较慢,或者还在 replay journal
  • BE 注册时,Follower 的 journal replay还没追上
  • Follower 的idToBackendRef还是空的

验证方法

-- 在 Follower FE 上执行SHOWFRONTENDS;-- 查看 ReplayedJournalId,如果比 Leader 小很多,说明还在同步SHOWBACKENDS;-- 如果看不到 BE,说明还没 replay 到 BE 注册的 EditLog

原因2:Follower 的 journal replay 卡住

场景

  • Follower 的 journal replay 遇到错误/异常,卡在某个 journal ID
  • 无法继续 replay 后续的 BE 注册 EditLog
  • 导致 Follower 永远看不到新注册的 BE

验证方法

# 在 Follower FE 上查看日志tail-100 fe/log/fe.log|grep-i"replay\|error\|exception"

原因3:BE 注册时 Follower 还没完全加入集群

场景

  • Follower FE2, FE3 虽然启动了,但可能还没完全加入集群(状态异常)
  • Leader 的 EditLog 可能还没同步到这些 Follower
  • 导致 Follower 看不到 BE

验证方法

-- 在 Leader FE 上执行SHOWFRONTENDS;-- 查看 Follower 的 Alive 状态和 ReplayedJournalId

解决方案

方案1:等待 Follower 同步完成(推荐)

操作

  1. 等待 Follower FE 的 journal replay 追上 Leader
  2. 确认 Follower 能看到所有 BE

验证

-- 在 Leader 上查看SHOWFRONTENDS;-- 确认 Follower 的 ReplayedJournalId 接近 Leader-- 在 Follower 上查看(如果能连接)SHOWBACKENDS;-- 确认能看到所有 BE

等待时间:通常需要1-5 分钟(取决于 journal 数量)

方案2:重启 Follower FE(如果同步卡住)

操作

  1. 停止 Follower FE
  2. 使用 Leader 作为 helper 重新启动
# 在 Follower FE 上执行./bin/stop_fe.sh# 使用 Leader 作为 helper 启动./bin/start_fe.sh --helper<leader_ip>:9010 --daemon# 查看启动日志,等待同步完成tail-f log/fe.log|grep-i"replay\|ready\|transfer"

预防措施

1. 正确的启动顺序

推荐顺序

  1. 先启动Leader FE,等待完全启动
  2. 再启动Follower FE,等待完全启动并同步完成
  3. 最后启动BE,让 BE 注册到 Leader

验证每个步骤

-- 步骤1:确认 Leader 启动SHOWFRONTENDS;-- 应该看到 1 个 Leader-- 步骤2:确认 Follower 启动并同步SHOWFRONTENDS;-- 应该看到 1 Leader + 2 Follower,且 (重要点)ReplayedJournalId 接近-- 步骤3:启动 BE 后,在所有 FE 上验证SHOWBACKENDS;-- 所有 FE 都应该能看到 BE

2. 监控 Follower 同步状态

定期检查

-- 在 Leader 上执行SHOWFRONTENDS;-- 关注:-- - Follower 的 Alive 状态-- - ReplayedJournalId 是否接近 Leader-- - LastHeartbeat 是否正常

3. 确保网络连通性

检查

  • Follower FE 能连接到 Leader FE(9010 端口)
  • Follower FE 能连接到 BE(9050 心跳端口)
  • Leader FE 能连接到所有 BE

代码关键点总结

  1. BE 注册只在连接的 FE(通常是 Leader)上立即生效

    • Leader 的idToBackendRef立即更新
    • 其他 FE 需要通过 EditLog Replay 才能看到
  2. Follower 的 BE 视图依赖 Journal Replay

    • replayAddBackend()方法更新 Follower 的idToBackendRef
    • 如果 Replay 还没追上,Follower 就看不到 BE
  3. 容量检查基于本地的idToBackendRef

    • getClusterAvailableCapacityB()idToBackendRef获取 BE 列表
    • 如果idToBackendRef为空,容量就是 0,触发错误

快速诊断命令

-- 1. 在 Leader 上检查 FE 状态SHOWFRONTENDS;-- 2. 在 Leader 上检查 BE 状态SHOWBACKENDS;-- 3. 在 Follower 上检查 BE 状态(如果能连接)SHOWBACKENDS;-- 4. 对比 Leader 和 Follower 的 ReplayedJournalId-- 如果差异很大,说明 Follower 还在同步
# 5. 在 Follower 上查看 journal replay 日志tail-100 fe/log/fe.log|grep-i"replay\|error\|exception"# 6. 检查 Follower 到 Leader 的网络连通性nc-zv<leader_ip>9010

总结

问题本质:Follower FE 的idToBackendRef还没同步到 BE 注册信息,导致容量检查失败。

根本原因:BE 注册信息通过 EditLog 同步,如果 Follower 的 journal replay 还没追上,就看不到 BE。

解决方法:等待 Follower 同步完成,或重启 Follower 使其从 Leader 重新同步。

预防措施:按正确顺序启动(Leader → Follower → BE),并确保 Follower 完全同步后再启动 BE。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 15:33:37

【微实验】仿AU音频编辑器开发实践:从零构建音频可视化工具

目录 项目构想与技术选型 核心架构设计 可视化实现的艺术 交互体验的细节处理 遇到的挑战与解决方案 附代码&#xff1a; 性能优化思考 总结与展望 项目构想与技术选型 音频处理涉及多个复杂的技术层面&#xff0c;从文件解码到信号处理&#xff0c;再到可视化呈现。…

作者头像 李华
网站建设 2026/6/10 15:32:32

数据中台权限设计

结合&#xff08;Spring Security MyBatis-Plus&#xff09;以及数据中台的通用架构&#xff0c;梳理了一套完整的权限设计方案&#xff0c;包含架构分层、核心设计以及时序交互流程。&#x1f3d7;️ 一、 整体架构设计在数据中台中&#xff0c;权限体系通常分为三个维度&…

作者头像 李华
网站建设 2026/6/10 16:50:23

Langchain-Chatchat与Neo4j图数据库结合:挖掘知识间深层关系

Langchain-Chatchat与Neo4j图数据库结合&#xff1a;挖掘知识间深层关系 在企业知识管理日益复杂的今天&#xff0c;一个普遍存在的痛点是&#xff1a;我们拥有海量文档&#xff0c;却难以从中快速获取真正有用的信息。传统的搜索方式依赖关键词匹配&#xff0c;结果常常是“找…

作者头像 李华
网站建设 2026/6/10 14:44:24

自抗扰控制(ADRC)这玩意儿玩起来挺有意思的。今天咱们就拆开它的内核看看,特别是怎么从传递函数推导到PID等效。先来段MATLAB代码热热身

自抗扰控制&#xff0c;幅频特性曲线&#xff0c;传函推导&#xff0c;pid等效&#xff0c;跟踪曲线&#xff0c;抗扰曲线。 s tf(s); G 1/(s^2 2*0.6*5*s 5^2); % 二阶振荡环节 bode(G), grid on 这代码画出来的幅频特性曲线能直观展示系统谐振峰的位置。注意看相位曲线…

作者头像 李华
网站建设 2026/6/10 16:15:48

单片机 433MHz 超再生模块发送接收 Proteus 仿真探秘

单片机433MHz超再生模块发送接收Proteus仿真源程序 使用Proteus7.8&#xff0c;实现超再生模块接收发送程序的仿真。 附有原理说明和单片机程序下载。 就是这种433M超再生收发模块&#xff1a;在电子制作的世界里&#xff0c;433MHz 超再生模块因其成本低、易实现等特点&#x…

作者头像 李华
网站建设 2026/6/10 16:07:19

基于改进A*算法的机器人路径规划MATLAB仿真:探索优化之路

6.基于改进A*算法的机器人路径规划MATLAB仿真程序&#xff08;含注释) 改进方法: 1、8个搜索方向变5个 2、冗余节点的删除 3、对评价函数f(n)进行改进 代码拿来可以直接用。在机器人路径规划领域&#xff0c;A算法一直是经典且应用广泛的方法。不过&#xff0c;为了让算法更加高…

作者头像 李华