GraphRAG 实战到底解决了什么问题?
2026/7/22 1:15:43
初始化流程:
问题现象:
Cluster has no available capacityBE 启动时,会通过MySQL 协议连接到 FE 并注册自己。关键点:
时间线: 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" 错误当 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);}关键点:
idToBackendRef立即更新(Leader 能立即看到 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());}}}关键点:
idToBackendRef只有在 Replay EditLog 时才会更新当 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 列表idToBackendRef还是空的(或只有部分 BE),容量就是 0场景:
idToBackendRef还是空的验证方法:
-- 在 Follower FE 上执行SHOWFRONTENDS;-- 查看 ReplayedJournalId,如果比 Leader 小很多,说明还在同步SHOWBACKENDS;-- 如果看不到 BE,说明还没 replay 到 BE 注册的 EditLog场景:
验证方法:
# 在 Follower FE 上查看日志tail-100 fe/log/fe.log|grep-i"replay\|error\|exception"场景:
验证方法:
-- 在 Leader FE 上执行SHOWFRONTENDS;-- 查看 Follower 的 Alive 状态和 ReplayedJournalId操作:
验证:
-- 在 Leader 上查看SHOWFRONTENDS;-- 确认 Follower 的 ReplayedJournalId 接近 Leader-- 在 Follower 上查看(如果能连接)SHOWBACKENDS;-- 确认能看到所有 BE等待时间:通常需要1-5 分钟(取决于 journal 数量)
操作:
# 在 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:确认 Leader 启动SHOWFRONTENDS;-- 应该看到 1 个 Leader-- 步骤2:确认 Follower 启动并同步SHOWFRONTENDS;-- 应该看到 1 Leader + 2 Follower,且 (重要点)ReplayedJournalId 接近-- 步骤3:启动 BE 后,在所有 FE 上验证SHOWBACKENDS;-- 所有 FE 都应该能看到 BE定期检查:
-- 在 Leader 上执行SHOWFRONTENDS;-- 关注:-- - Follower 的 Alive 状态-- - ReplayedJournalId 是否接近 Leader-- - LastHeartbeat 是否正常检查:
BE 注册只在连接的 FE(通常是 Leader)上立即生效
idToBackendRef立即更新Follower 的 BE 视图依赖 Journal Replay
replayAddBackend()方法更新 Follower 的idToBackendRef容量检查基于本地的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。