From a4637e446223fde585e0c746092135210d8b0746 Mon Sep 17 00:00:00 2001 From: walter Date: Fri, 3 Nov 2023 14:33:06 +0800 Subject: [PATCH] [fix](fe) Add/remove frontends after updating BEBJE (#26313) To ensure exception safety, adding or removing frontends in memory should execute after removing the electable nodes (might throw exceptions) --- .../java/org/apache/doris/catalog/Env.java | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java index 29122a1042..1cbdcc12a1 100755 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java @@ -2678,16 +2678,20 @@ public class Env { throw new DdlException("frontend name already exists " + nodeName + ". Try again"); } - fe = new Frontend(role, nodeName, host, editLogPort); - LOG.info("add frontend: {}", fe); - - frontends.put(nodeName, fe); BDBHA bdbha = (BDBHA) haProtocol; + bdbha.removeConflictNodeIfExist(host, editLogPort); + int targetFollowerCount = getFollowerCount() + 1; if (role == FrontendNodeType.FOLLOWER || role == FrontendNodeType.REPLICA) { helperNodes.add(new HostInfo(host, editLogPort)); - bdbha.addUnReadyElectableNode(nodeName, getFollowerCount()); + bdbha.addUnReadyElectableNode(nodeName, targetFollowerCount); } - bdbha.removeConflictNodeIfExist(host, editLogPort); + + // Only add frontend after removing the conflict nodes, to ensure the exception safety. + fe = new Frontend(role, nodeName, host, editLogPort); + frontends.put(nodeName, fe); + + LOG.info("add frontend: {}", fe); + editLog.logAddFrontend(fe); } finally { unlock(); @@ -2748,17 +2752,21 @@ public class Env { .getHostPortInAccessibleFormat(host, port) + "]"); } - LOG.info("remove frontend: {}", fe); - - frontends.remove(fe.getNodeName()); - removedFrontends.add(fe.getNodeName()); - + int targetFollowerCount = getFollowerCount() - 1; if (fe.getRole() == FrontendNodeType.FOLLOWER || fe.getRole() == FrontendNodeType.REPLICA) { haProtocol.removeElectableNode(fe.getNodeName()); removeHelperNode(host, port); BDBHA ha = (BDBHA) haProtocol; - ha.removeUnReadyElectableNode(fe.getNodeName(), getFollowerCount()); + ha.removeUnReadyElectableNode(fe.getNodeName(), targetFollowerCount); } + + LOG.info("remove frontend: {}", fe); + + // Only remove frontend after removing the electable node success, to ensure the + // exception safety. + frontends.remove(fe.getNodeName()); + removedFrontends.add(fe.getNodeName()); + editLog.logRemoveFrontend(fe); } finally { unlock();