This is an automated email from the ASF dual-hosted git repository.

tanxinyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new f52d752bf84 Region migration related work (#12293)
f52d752bf84 is described below

commit f52d752bf84e1a05a75db04e84125ecb49072a73
Author: Li Yu Heng <[email protected]>
AuthorDate: Fri Apr 12 19:09:52 2024 +0800

    Region migration related work (#12293)
---
 .../iotdb/it/env/cluster/env/AbstractEnv.java      |  29 +-
 .../it/env/cluster/node/AbstractNodeWrapper.java   |   5 +
 .../apache/iotdb/itbase/env/BaseNodeWrapper.java   |   2 +
 ...IoTDBRegionMigrateDataNodeCrashITFramework.java |  15 +-
 .../IoTDBRegionMigrateReliabilityITFramework.java  | 412 +++++++++++++++------
 .../it/regionmigration/KillPointContext.java       |  22 +-
 .../pass/IoTDBRegionMigrateClusterCrashIT.java     |  68 ++++
 .../pass/IoTDBRegionMigrateConfigNodeCrashIT.java  |  92 ++++-
 .../pass/IoTDBRegionMigrateNormalIT.java           |   8 +-
 .../pass/IoTDBRegionMigrateOtherIT.java            |   9 +-
 ...ateCoordinatorCrashWhenRemoveRemotePeerIT.java} |  24 +-
 .../IoTDBRegionMigrateDataNodeCrashIT.java         |  59 ++-
 ...MigrateOriginalCrashWhenDeleteLocalPeerIT.java} |  19 +-
 ...igrateOriginalCrashWhenRemoveRemotePeerIT.java} |  19 +-
 .../apache/iotdb/rpc/TElasticFramedTransport.java  |   3 +-
 .../client/async/AsyncDataNodeClientPool.java      |   7 +
 .../client/async/handlers/AsyncClientHandler.java  |   1 +
 .../iotdb/confignode/manager/ProcedureManager.java |   9 +-
 .../iotdb/confignode/procedure/Procedure.java      |  15 -
 .../procedure/env/RegionMaintainHandler.java       |  85 +++--
 .../procedure/impl/StateMachineProcedure.java      |  18 +
 .../impl/region/AddRegionPeerProcedure.java        |  91 +++--
 .../impl/region/RemoveRegionPeerProcedure.java     |  23 +-
 .../testonly/CreateManyDatabasesProcedure.java     |  10 +-
 iotdb-core/consensus/pom.xml                       |   4 +
 .../org/apache/iotdb/consensus/IConsensus.java     |  19 +
 .../consensus/exception/ConsensusException.java    |   4 +
 .../apache/iotdb/consensus/iot/IoTConsensus.java   |  91 +++--
 .../consensus/iot/IoTConsensusServerImpl.java      | 130 +++++--
 .../service/IoTConsensusRPCServiceProcessor.java   |   8 +-
 .../iotdb/consensus/ratis/RatisConsensus.java      |  37 +-
 .../iotdb/consensus/simple/SimpleConsensus.java    |  11 +
 .../apache/iotdb/consensus/iot/ReplicateTest.java  |  21 ++
 .../apache/iotdb/consensus/iot/StabilityTest.java  |  12 +-
 .../iotdb/consensus/ratis/RatisConsensusTest.java  |  19 +
 .../dataregion/DataRegionStateMachine.java         |  15 +-
 .../java/org/apache/iotdb/db/service/DataNode.java |  69 +---
 .../iotdb/db/service/RegionMigrateService.java     |   7 +-
 .../dataregion/snapshot/SnapshotLoader.java        |   6 -
 ... => IoTConsensusDeleteLocalPeerKillPoints.java} |   8 +-
 ...a => IoTConsensusInactivatePeerKillPoints.java} |   8 +-
 ...TConsensusRemovePeerCoordinatorKillPoints.java} |   2 +-
 ...nsusRemovePeerKillPoints.java => KillNode.java} |  11 +-
 .../src/main/thrift/iotconsensus.thrift            |   1 +
 44 files changed, 1114 insertions(+), 414 deletions(-)

diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
index 68be2f40c51..5b64cb87234 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
@@ -468,7 +468,8 @@ public abstract class AbstractEnv implements BaseEnv {
       dataNode = this.dataNodeWrapperList.get(0);
     }
 
-    return getWriteConnectionWithSpecifiedDataNode(dataNode, version, 
username, password);
+    return getWriteConnectionFromDataNodeList(
+        this.dataNodeWrapperList, version, username, password);
   }
 
   protected NodeConnection getWriteConnectionWithSpecifiedDataNode(
@@ -487,6 +488,26 @@ public abstract class AbstractEnv implements BaseEnv {
         writeConnection);
   }
 
+  protected NodeConnection getWriteConnectionFromDataNodeList(
+      List<DataNodeWrapper> dataNodeList,
+      Constant.Version version,
+      String username,
+      String password)
+      throws SQLException {
+    List<DataNodeWrapper> dataNodeWrapperListCopy = new 
ArrayList<>(dataNodeList);
+    Collections.shuffle(dataNodeWrapperListCopy);
+    SQLException lastException = null;
+    for (DataNodeWrapper dataNode : dataNodeWrapperListCopy) {
+      try {
+        return getWriteConnectionWithSpecifiedDataNode(dataNode, version, 
username, password);
+      } catch (SQLException e) {
+        lastException = e;
+      }
+    }
+    logger.error("Failed to get connection from any DataNode, last exception 
is ", lastException);
+    throw lastException;
+  }
+
   protected List<NodeConnection> getReadConnections(
       Constant.Version version, String username, String password) throws 
SQLException {
     List<String> endpoints = new ArrayList<>();
@@ -600,6 +621,12 @@ public abstract class AbstractEnv implements BaseEnv {
     return dataNodeWrapperList;
   }
 
+  public List<AbstractNodeWrapper> getNodeWrapperList() {
+    List<AbstractNodeWrapper> result = new ArrayList<>(configNodeWrapperList);
+    result.addAll(dataNodeWrapperList);
+    return result;
+  }
+
   /**
    * Get connection to ConfigNode-Leader in ClusterIT environment
    *
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AbstractNodeWrapper.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AbstractNodeWrapper.java
index a517fc95829..45a1188a4ca 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AbstractNodeWrapper.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/AbstractNodeWrapper.java
@@ -502,6 +502,11 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
     }
   }
 
+  @Override
+  public boolean isAlive() {
+    return this.instance != null && this.instance.isAlive();
+  }
+
   @Override
   public final String getIp() {
     return this.nodeAddress;
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseNodeWrapper.java
 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseNodeWrapper.java
index 73cd372b634..cd0eb86bde1 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseNodeWrapper.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseNodeWrapper.java
@@ -33,6 +33,8 @@ public interface BaseNodeWrapper {
 
   void stopForcibly();
 
+  boolean isAlive();
+
   String getIp();
 
   int getPort();
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/IoTDBRegionMigrateDataNodeCrashITFramework.java
similarity index 65%
copy from 
iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
copy to 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/IoTDBRegionMigrateDataNodeCrashITFramework.java
index 385ecaa89fc..4a363d196e7 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/IoTDBRegionMigrateDataNodeCrashITFramework.java
@@ -17,15 +17,14 @@
  * under the License.
  */
 
-package org.apache.iotdb.consensus.exception;
+package org.apache.iotdb.confignode.it.regionmigration;
 
-public class ConsensusException extends Exception {
+import org.apache.iotdb.commons.utils.KillPoint.KillNode;
 
-  public ConsensusException(String message) {
-    super(message);
-  }
-
-  public ConsensusException(String message, Throwable cause) {
-    super(message, cause);
+public class IoTDBRegionMigrateDataNodeCrashITFramework
+    extends IoTDBRegionMigrateReliabilityITFramework {
+  @SafeVarargs
+  public final <T extends Enum<T>> void success(T... dataNodeKillPoints) 
throws Exception {
+    successTest(1, 1, 1, 2, noKillPoints(), buildSet(dataNodeKillPoints), 
KillNode.ALL_NODES);
   }
 }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/IoTDBRegionMigrateReliabilityITFramework.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/IoTDBRegionMigrateReliabilityITFramework.java
index 3f33c857fcd..0994ddfb389 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/IoTDBRegionMigrateReliabilityITFramework.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/IoTDBRegionMigrateReliabilityITFramework.java
@@ -20,18 +20,26 @@
 package org.apache.iotdb.confignode.it.regionmigration;
 
 import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
+import org.apache.iotdb.commons.client.sync.SyncConfigNodeIServiceClient;
 import org.apache.iotdb.commons.concurrent.IoTDBThreadPoolFactory;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.commons.utils.KillPoint.KillNode;
 import org.apache.iotdb.commons.utils.KillPoint.KillPoint;
+import org.apache.iotdb.confignode.rpc.thrift.TRegionInfo;
+import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
+import org.apache.iotdb.confignode.rpc.thrift.TShowRegionResp;
 import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.consensus.iot.IoTConsensusServerImpl;
 import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
 import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.env.cluster.env.AbstractEnv;
 import org.apache.iotdb.it.env.cluster.node.AbstractNodeWrapper;
 import org.apache.iotdb.it.env.cluster.node.ConfigNodeWrapper;
+import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
 import org.apache.iotdb.itbase.exception.InconsistentDataException;
 import org.apache.iotdb.metrics.utils.SystemType;
 
+import org.apache.thrift.TException;
 import org.awaitility.Awaitility;
 import org.awaitility.core.ConditionTimeoutException;
 import org.junit.After;
@@ -50,8 +58,10 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
@@ -61,18 +71,48 @@ import java.util.concurrent.ConcurrentHashMap.KeySetView;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 public class IoTDBRegionMigrateReliabilityITFramework {
   private static final Logger LOGGER =
       LoggerFactory.getLogger(IoTDBRegionMigrateReliabilityITFramework.class);
-  private static final String INSERTION =
-      "INSERT INTO root.sg.d1(timestamp,speed,temperature) values(100, 10.1, 
20.7)";
+  private static final String INSERTION1 =
+      "INSERT INTO root.sg.d1(timestamp,speed,temperature) values(100, 1, 2)";
+  private static final String INSERTION2 =
+      "INSERT INTO root.sg.d1(timestamp,speed,temperature) values(101, 3, 4)";
+  private static final String FLUSH_COMMAND = "flush";
   private static final String SHOW_REGIONS = "show regions";
   private static final String SHOW_DATANODES = "show datanodes";
+  private static final String COUNT_TIMESERIES = "select count(*) from 
root.sg.**";
   private static final String REGION_MIGRATE_COMMAND_FORMAT = "migrate region 
%d from %d to %d";
+  private static final String CONFIGURATION_FILE_NAME = "configuration.dat";
   ExecutorService executorService = 
IoTDBThreadPoolFactory.newCachedThreadPool("regionMigrateIT");
 
+  public static Consumer<KillPointContext> actionOfKillNode =
+      context -> {
+        context.getNodeWrapper().stopForcibly();
+        LOGGER.info("Node {} stopped.", context.getNodeWrapper().getId());
+        Assert.assertFalse(context.getNodeWrapper().isAlive());
+        if (context.getNodeWrapper() instanceof ConfigNodeWrapper) {
+          context.getNodeWrapper().start();
+          LOGGER.info("Node {} restarted.", context.getNodeWrapper().getId());
+          Assert.assertTrue(context.getNodeWrapper().isAlive());
+        }
+      };
+
+  public static Consumer<KillPointContext> actionOfRestartCluster =
+      context -> {
+        context
+            .getEnv()
+            .getNodeWrapperList()
+            .parallelStream()
+            .forEach(AbstractNodeWrapper::stopForcibly);
+        LOGGER.info("Cluster has been stopped");
+        
context.getEnv().getNodeWrapperList().parallelStream().forEach(AbstractNodeWrapper::start);
+        LOGGER.info("Cluster has been restarted");
+      };
+
   @Before
   public void setUp() throws Exception {
     EnvFactory.getEnv()
@@ -94,7 +134,8 @@ public class IoTDBRegionMigrateReliabilityITFramework {
       final int configNodeNum,
       final int dataNodeNum,
       KeySetView<String, Boolean> killConfigNodeKeywords,
-      KeySetView<String, Boolean> killDataNodeKeywords)
+      KeySetView<String, Boolean> killDataNodeKeywords,
+      KillNode killNode)
       throws Exception {
     generalTestWithAllOptions(
         dataReplicateFactor,
@@ -103,10 +144,9 @@ public class IoTDBRegionMigrateReliabilityITFramework {
         dataNodeNum,
         killConfigNodeKeywords,
         killDataNodeKeywords,
+        actionOfKillNode,
         true,
-        true,
-        0,
-        true);
+        killNode);
   }
 
   public void failTest(
@@ -115,7 +155,8 @@ public class IoTDBRegionMigrateReliabilityITFramework {
       final int configNodeNum,
       final int dataNodeNum,
       KeySetView<String, Boolean> killConfigNodeKeywords,
-      KeySetView<String, Boolean> killDataNodeKeywords)
+      KeySetView<String, Boolean> killDataNodeKeywords,
+      KillNode killNode)
       throws Exception {
     generalTestWithAllOptions(
         dataReplicateFactor,
@@ -124,23 +165,38 @@ public class IoTDBRegionMigrateReliabilityITFramework {
         dataNodeNum,
         killConfigNodeKeywords,
         killDataNodeKeywords,
-        true,
-        true,
-        60,
-        false);
+        actionOfKillNode,
+        false,
+        killNode);
+  }
+
+  public void killClusterTest(
+      KeySetView<String, Boolean> configNodeKeywords, boolean 
expectMigrateSuccess)
+      throws Exception {
+    generalTestWithAllOptions(
+        2,
+        3,
+        3,
+        3,
+        configNodeKeywords,
+        noKillPoints(),
+        actionOfRestartCluster,
+        expectMigrateSuccess,
+        KillNode.ALL_NODES);
   }
 
+  // region general test
+
   public void generalTestWithAllOptions(
       final int dataReplicateFactor,
       final int schemaReplicationFactor,
       final int configNodeNum,
       final int dataNodeNum,
-      KeySetView<String, Boolean> killConfigNodeKeywords,
-      KeySetView<String, Boolean> killDataNodeKeywords,
-      final boolean checkOriginalRegionDirDeleted,
-      final boolean checkConfigurationFileDeleted,
-      final int restartTime,
-      final boolean isMigrateSuccess)
+      KeySetView<String, Boolean> configNodeKeywords,
+      KeySetView<String, Boolean> dataNodeKeywords,
+      Consumer<KillPointContext> actionWhenDetectKeyWords,
+      final boolean expectMigrateSuccess,
+      KillNode killNode)
       throws Exception {
     // prepare env
     EnvFactory.getEnv()
@@ -148,14 +204,16 @@ public class IoTDBRegionMigrateReliabilityITFramework {
         .getCommonConfig()
         .setDataReplicationFactor(dataReplicateFactor)
         .setSchemaReplicationFactor(schemaReplicationFactor);
-    EnvFactory.getEnv().registerConfigNodeKillPoints(new 
ArrayList<>(killConfigNodeKeywords));
-    EnvFactory.getEnv().registerDataNodeKillPoints(new 
ArrayList<>(killDataNodeKeywords));
+    EnvFactory.getEnv().registerConfigNodeKillPoints(new 
ArrayList<>(configNodeKeywords));
+    EnvFactory.getEnv().registerDataNodeKillPoints(new 
ArrayList<>(dataNodeKeywords));
     EnvFactory.getEnv().initClusterEnvironment(configNodeNum, dataNodeNum);
 
     try (final Connection connection = EnvFactory.getEnv().getConnection();
-        final Statement statement = connection.createStatement()) {
+        final Statement statement = connection.createStatement();
+        SyncConfigNodeIServiceClient client =
+            (SyncConfigNodeIServiceClient) 
EnvFactory.getEnv().getLeaderConfigNodeConnection()) {
 
-      statement.execute(INSERTION);
+      statement.execute(INSERTION1);
 
       ResultSet result = statement.executeQuery(SHOW_REGIONS);
       Map<Integer, Set<Integer>> regionMap = getRegionMap(result);
@@ -173,29 +231,35 @@ public class IoTDBRegionMigrateReliabilityITFramework {
       checkRegionFileExist(originalDataNode);
       checkPeersExist(regionMap.get(selectedRegion), originalDataNode, 
selectedRegion);
 
-      // set kill points
-      setConfigNodeKillPoints(killConfigNodeKeywords, restartTime);
-      setDataNodeKillPoints(killDataNodeKeywords, restartTime);
-
-      // region migration start
-      statement.execute(regionMigrateCommand(selectedRegion, originalDataNode, 
destDataNode));
-
-      boolean success = false;
       try {
-        awaitUntilSuccess(statement, selectedRegion, originalDataNode, 
destDataNode);
-        success = true;
+        awaitUntilFlush(statement, originalDataNode);
       } catch (ConditionTimeoutException e) {
-        LOGGER.error("Region migrate failed", e);
+        LOGGER.error("Flush timeout:", e);
+        Assert.fail();
       }
-      // Assert.assertTrue(isMigrateSuccess == success);
-
-      // make sure all kill points have been triggered
-      checkKillPointsAllTriggered(killConfigNodeKeywords);
-      checkKillPointsAllTriggered(killDataNodeKeywords);
 
-      if (!success) {
-        restartAllDataNodes();
+      // set kill points
+      if (killNode == KillNode.ORIGINAL_DATANODE) {
+        setDataNodeKillPoints(
+            Collections.singletonList(
+                
EnvFactory.getEnv().dataNodeIdToWrapper(originalDataNode).get()),
+            dataNodeKeywords,
+            actionWhenDetectKeyWords);
+      } else if (killNode == KillNode.DESTINATION_DATANODE) {
+        setDataNodeKillPoints(
+            
Collections.singletonList(EnvFactory.getEnv().dataNodeIdToWrapper(destDataNode).get()),
+            dataNodeKeywords,
+            actionWhenDetectKeyWords);
+      } else {
+        setConfigNodeKillPoints(configNodeKeywords, actionWhenDetectKeyWords);
+        setDataNodeKillPoints(
+            EnvFactory.getEnv().getDataNodeWrapperList(),
+            dataNodeKeywords,
+            actionWhenDetectKeyWords);
       }
+
+      LOGGER.info("DataNode set before migration: {}", 
regionMap.get(selectedRegion));
+
       System.out.println(
           "originalDataNode: "
               + 
EnvFactory.getEnv().dataNodeIdToWrapper(originalDataNode).get().getNodePath());
@@ -203,75 +267,103 @@ public class IoTDBRegionMigrateReliabilityITFramework {
           "destDataNode: "
               + 
EnvFactory.getEnv().dataNodeIdToWrapper(destDataNode).get().getNodePath());
 
-      // check if there is anything remain
-      if (checkOriginalRegionDirDeleted) {
-        if (success) {
-          checkRegionFileClear(originalDataNode);
-          checkRegionFileExist(destDataNode);
-        } else {
-          checkRegionFileClear(destDataNode);
-          checkRegionFileExist(originalDataNode);
+      // region migration start
+      statement.execute(buildRegionMigrateCommand(selectedRegion, 
originalDataNode, destDataNode));
+
+      boolean success = false;
+      try {
+        awaitUntilSuccess(client, selectedRegion, originalDataNode, 
destDataNode);
+        success = true;
+      } catch (ConditionTimeoutException e) {
+        if (expectMigrateSuccess) {
+          LOGGER.error("Region migrate failed", e);
+          Assert.fail();
         }
       }
-      if (checkConfigurationFileDeleted) {
-        if (success) {
-          checkPeersClear(allDataNodeId, originalDataNode, selectedRegion);
-        } else {
-          checkPeersClear(allDataNodeId, destDataNode, selectedRegion);
-        }
+      if (!expectMigrateSuccess && success) {
+        LOGGER.error("Region migrate succeeded unexpectedly");
+        Assert.fail();
       }
 
+      // make sure all kill points have been triggered
+      checkKillPointsAllTriggered(configNodeKeywords);
+      checkKillPointsAllTriggered(dataNodeKeywords);
+
+      // check the remaining file
+      if (success) {
+        checkRegionFileClearIfNodeAlive(originalDataNode);
+        checkRegionFileExistIfNodeAlive(destDataNode);
+        checkPeersClearIfNodeAlive(allDataNodeId, originalDataNode, 
selectedRegion);
+        checkClusterStillWritable();
+      } else {
+        checkRegionFileClearIfNodeAlive(destDataNode);
+        checkRegionFileExistIfNodeAlive(originalDataNode);
+        checkPeersClearIfNodeAlive(allDataNodeId, destDataNode, 
selectedRegion);
+      }
     } catch (InconsistentDataException ignore) {
 
     }
     LOGGER.info("test pass");
   }
 
-  private void restartAllDataNodes() {
-    EnvFactory.getEnv()
-        .getDataNodeWrapperList()
+  private void restartDataNodes(List<DataNodeWrapper> dataNodeWrappers) {
+    dataNodeWrappers
         .parallelStream()
         .forEach(
             nodeWrapper -> {
-              nodeWrapper.stopForcibly();
+              nodeWrapper.stop();
+              Awaitility.await()
+                  .atMost(1, TimeUnit.MINUTES)
+                  .pollDelay(2, TimeUnit.SECONDS)
+                  .until(() -> !nodeWrapper.isAlive());
+              LOGGER.info("Node {} stopped.", nodeWrapper.getId());
               nodeWrapper.start();
+              Awaitility.await()
+                  .atMost(1, TimeUnit.MINUTES)
+                  .pollDelay(2, TimeUnit.SECONDS)
+                  .until(nodeWrapper::isAlive);
+              try {
+                TimeUnit.SECONDS.sleep(10);
+              } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+              }
+              LOGGER.info("Node {} restarted.", nodeWrapper.getId());
             });
   }
 
   private void setConfigNodeKillPoints(
-      KeySetView<String, Boolean> killConfigNodeKeywords, int nodeRestartTime) 
{
+      KeySetView<String, Boolean> killConfigNodeKeywords, 
Consumer<KillPointContext> action) {
     EnvFactory.getEnv()
         .getConfigNodeWrapperList()
         .forEach(
             configNodeWrapper ->
                 executorService.submit(
                     () ->
-                        nodeLogKillPoint(
-                            configNodeWrapper, killConfigNodeKeywords, 
nodeRestartTime)));
+                        doActionWhenDetectKeywords(
+                            configNodeWrapper, killConfigNodeKeywords, 
action)));
   }
 
   private void setDataNodeKillPoints(
-      KeySetView<String, Boolean> killDataNodeKeywords, int nodeRestartTime) {
-    EnvFactory.getEnv()
-        .getDataNodeWrapperList()
-        .forEach(
-            dataNodeWrapper ->
-                executorService.submit(
-                    () ->
-                        nodeLogKillPoint(dataNodeWrapper, 
killDataNodeKeywords, nodeRestartTime)));
+      List<DataNodeWrapper> dataNodeWrappers,
+      KeySetView<String, Boolean> killDataNodeKeywords,
+      Consumer<KillPointContext> action) {
+    dataNodeWrappers.forEach(
+        dataNodeWrapper ->
+            executorService.submit(
+                () -> doActionWhenDetectKeywords(dataNodeWrapper, 
killDataNodeKeywords, action)));
   }
 
   /**
    * Monitor the node's log and kill it when detect specific log.
    *
    * @param nodeWrapper Easy to understand
-   * @param killNodeKeywords When detect these keywords in node's log, stop 
the node forcibly
+   * @param keywords When detect these keywords in node's log, stop the node 
forcibly
    */
-  private static void nodeLogKillPoint(
+  private static void doActionWhenDetectKeywords(
       AbstractNodeWrapper nodeWrapper,
-      KeySetView<String, Boolean> killNodeKeywords,
-      int restartTime) {
-    if (killNodeKeywords.isEmpty()) {
+      KeySetView<String, Boolean> keywords,
+      Consumer<KillPointContext> action) {
+    if (keywords.isEmpty()) {
       return;
     }
     final String logFileName;
@@ -314,32 +406,20 @@ public class IoTDBRegionMigrateReliabilityITFramework {
           // if trigger more than one keyword at a same time, test code may 
have mistakes
           Assert.assertTrue(
               line,
-              killNodeKeywords.stream()
-                      .map(KillPoint::addKillPointPrefix)
-                      .filter(line::contains)
-                      .count()
+              
keywords.stream().map(KillPoint::addKillPointPrefix).filter(line::contains).count()
                   <= 1);
           String finalLine = line;
           Optional<String> detectedKeyword =
-              killNodeKeywords.stream()
+              keywords.stream()
                   .filter(keyword -> 
finalLine.contains(KillPoint.addKillPointPrefix(keyword)))
                   .findAny();
           if (detectedKeyword.isPresent()) {
             // each keyword only trigger once
-            killNodeKeywords.remove(detectedKeyword.get());
-            LOGGER.info("Kill point is triggered: {}", detectedKeyword);
-            // reboot the node
-            nodeWrapper.stopForcibly();
-            if (restartTime > 0) {
-              try {
-                TimeUnit.SECONDS.sleep(restartTime);
-              } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-              }
-            }
-            nodeWrapper.start();
+            keywords.remove(detectedKeyword.get());
+            action.accept(new KillPointContext(nodeWrapper, (AbstractEnv) 
EnvFactory.getEnv()));
+            LOGGER.info("Kill point triggered: {}", detectedKeyword.get());
           }
-          if (killNodeKeywords.isEmpty()) {
+          if (keywords.isEmpty()) {
             break;
           }
         }
@@ -359,8 +439,10 @@ public class IoTDBRegionMigrateReliabilityITFramework {
     }
   }
 
-  private static String regionMigrateCommand(int who, int from, int to) {
-    return String.format(REGION_MIGRATE_COMMAND_FORMAT, who, from, to);
+  private static String buildRegionMigrateCommand(int who, int from, int to) {
+    String result = String.format(REGION_MIGRATE_COMMAND_FORMAT, who, from, 
to);
+    LOGGER.info(result);
+    return result;
   }
 
   private static Map<Integer, Set<Integer>> getRegionMap(ResultSet 
showRegionsResult)
@@ -369,15 +451,26 @@ public class IoTDBRegionMigrateReliabilityITFramework {
     while (showRegionsResult.next()) {
       if (String.valueOf(TConsensusGroupType.DataRegion)
           .equals(showRegionsResult.getString(ColumnHeaderConstant.TYPE))) {
-        int region = showRegionsResult.getInt(ColumnHeaderConstant.REGION_ID);
-        int dataNode = 
showRegionsResult.getInt(ColumnHeaderConstant.DATA_NODE_ID);
-        regionMap.putIfAbsent(region, new HashSet<>());
-        regionMap.get(region).add(dataNode);
+        int regionId = 
showRegionsResult.getInt(ColumnHeaderConstant.REGION_ID);
+        int dataNodeId = 
showRegionsResult.getInt(ColumnHeaderConstant.DATA_NODE_ID);
+        regionMap.computeIfAbsent(regionId, id -> new 
HashSet<>()).add(dataNodeId);
       }
     }
     return regionMap;
   }
 
+  private static Map<Integer, Set<Integer>> getRegionMap(List<TRegionInfo> 
regionInfoList) {
+    Map<Integer, Set<Integer>> regionMap = new HashMap<>();
+    regionInfoList.forEach(
+        regionInfo -> {
+          int regionId = regionInfo.getConsensusGroupId().getId();
+          regionMap
+              .computeIfAbsent(regionId, regionId1 -> new HashSet<>())
+              .add(regionInfo.getDataNodeId());
+        });
+    return regionMap;
+  }
+
   private static int selectRegion(Map<Integer, Set<Integer>> regionMap) {
     return regionMap.keySet().stream().findAny().orElseThrow(() -> new 
RuntimeException("gg"));
   }
@@ -397,21 +490,55 @@ public class IoTDBRegionMigrateReliabilityITFramework {
         .orElseThrow(() -> new RuntimeException("cannot find dest DataNode"));
   }
 
+  private static void awaitUntilFlush(Statement statement, int 
originalDataNode) {
+    long startTime = System.currentTimeMillis();
+    File sequence = new File(buildDataPath(originalDataNode, true));
+    File unsequence = new File(buildDataPath(originalDataNode, false));
+    Awaitility.await()
+        .atMost(1, TimeUnit.MINUTES)
+        .pollDelay(2, TimeUnit.SECONDS)
+        .until(
+            () -> {
+              statement.execute(FLUSH_COMMAND);
+              int fileNum = 0;
+              if (sequence.exists() && sequence.listFiles() != null) {
+                fileNum += Objects.requireNonNull(sequence.listFiles()).length;
+              }
+              if (unsequence.exists() && unsequence.listFiles() != null) {
+                fileNum += 
Objects.requireNonNull(unsequence.listFiles()).length;
+              }
+              return fileNum > 0;
+            });
+    LOGGER.info("DataNode {} has been flushed", originalDataNode);
+    LOGGER.info("Flush cost time: {}ms", System.currentTimeMillis() - 
startTime);
+  }
+
   private static void awaitUntilSuccess(
-      Statement statement, int selectedRegion, int originalDataNode, int 
destDataNode) {
+      SyncConfigNodeIServiceClient client,
+      int selectedRegion,
+      int originalDataNode,
+      int destDataNode) {
     AtomicReference<Set<Integer>> lastTimeDataNodes = new AtomicReference<>();
     AtomicReference<Exception> lastException = new AtomicReference<>();
+    AtomicReference<SyncConfigNodeIServiceClient> clientRef = new 
AtomicReference<>(client);
     try {
       Awaitility.await()
-          .atMost(2, TimeUnit.MINUTES)
+          .atMost(1, TimeUnit.MINUTES)
+          .pollDelay(2, TimeUnit.SECONDS)
           .until(
               () -> {
                 try {
-                  Map<Integer, Set<Integer>> newRegionMap =
-                      getRegionMap(statement.executeQuery(SHOW_REGIONS));
+                  TShowRegionResp resp = clientRef.get().showRegion(new 
TShowRegionReq());
+                  Map<Integer, Set<Integer>> newRegionMap = 
getRegionMap(resp.getRegionInfoList());
                   Set<Integer> dataNodes = newRegionMap.get(selectedRegion);
                   lastTimeDataNodes.set(dataNodes);
                   return !dataNodes.contains(originalDataNode) && 
dataNodes.contains(destDataNode);
+                } catch (TException e) {
+                  clientRef.set(
+                      (SyncConfigNodeIServiceClient)
+                          EnvFactory.getEnv().getLeaderConfigNodeConnection());
+                  lastException.set(e);
+                  return false;
                 } catch (Exception e) {
                   // Any exception can be ignored
                   lastException.set(e);
@@ -429,9 +556,21 @@ public class IoTDBRegionMigrateReliabilityITFramework {
       lastTimeDataNodes.get().remove(originalDataNode);
       lastTimeDataNodes.get().add(destDataNode);
       String expectSetStr = lastTimeDataNodes.toString();
-      LOGGER.info("DataNode Set {} is unexpected, expect {}", actualSetStr, 
expectSetStr);
+      LOGGER.error("DataNode Set {} is unexpected, expect {}", actualSetStr, 
expectSetStr);
+      if (lastException.get() == null) {
+        LOGGER.info("No exception during awaiting");
+      } else {
+        LOGGER.error("Last exception during awaiting:", lastException.get());
+      }
       throw e;
     }
+    LOGGER.info("DataNode set has been successfully changed to {}", 
lastTimeDataNodes.get());
+  }
+
+  private static void checkRegionFileExistIfNodeAlive(int dataNode) {
+    if (EnvFactory.getEnv().dataNodeIdToWrapper(dataNode).get().isAlive()) {
+      checkRegionFileExist(dataNode);
+    }
   }
 
   private static void checkRegionFileExist(int dataNode) {
@@ -440,18 +579,37 @@ public class IoTDBRegionMigrateReliabilityITFramework {
     Assert.assertNotEquals(0, 
Objects.requireNonNull(originalRegionDir.listFiles()).length);
   }
 
+  private static void checkRegionFileClearIfNodeAlive(int dataNode) {
+    if (EnvFactory.getEnv().dataNodeIdToWrapper(dataNode).get().isAlive()) {
+      checkRegionFileClear(dataNode);
+    }
+  }
+
   /** Check whether the original DataNode's region file has been deleted. */
   private static void checkRegionFileClear(int dataNode) {
     File originalRegionDir = new File(buildRegionDirPath(dataNode));
     Assert.assertTrue(originalRegionDir.isDirectory());
     Assert.assertEquals(0, 
Objects.requireNonNull(originalRegionDir.listFiles()).length);
-    LOGGER.info("Original region clear");
+    LOGGER.info("Original DataNode {} region file clear", dataNode);
+  }
+
+  private static void checkPeersExistIfNodeAlive(
+      Set<Integer> dataNodes, int originalDataNode, int regionId) {
+    dataNodes.forEach(
+        targetDataNode -> checkPeerExistIfNodeAlive(targetDataNode, 
originalDataNode, regionId));
   }
 
   private static void checkPeersExist(Set<Integer> dataNodes, int 
originalDataNode, int regionId) {
     dataNodes.forEach(targetDataNode -> checkPeerExist(targetDataNode, 
originalDataNode, regionId));
   }
 
+  private static void checkPeerExistIfNodeAlive(
+      int checkTargetDataNode, int originalDataNode, int regionId) {
+    if 
(EnvFactory.getEnv().dataNodeIdToWrapper(checkTargetDataNode).get().isAlive()) {
+      checkPeerExist(checkTargetDataNode, originalDataNode, regionId);
+    }
+  }
+
   private static void checkPeerExist(int checkTargetDataNode, int 
originalDataNode, int regionId) {
     File expectExistedFile =
         new File(buildConfigurationDataFilePath(checkTargetDataNode, 
originalDataNode, regionId));
@@ -460,6 +618,15 @@ public class IoTDBRegionMigrateReliabilityITFramework {
         expectExistedFile.exists());
   }
 
+  private static void checkPeersClearIfNodeAlive(
+      Set<Integer> dataNodes, int originalDataNode, int regionId) {
+    dataNodes.stream()
+        .filter(dataNode -> dataNode != originalDataNode)
+        .forEach(
+            targetDataNode ->
+                checkPeerClearIfNodeAlive(targetDataNode, originalDataNode, 
regionId));
+  }
+
   private static void checkPeersClear(Set<Integer> dataNodes, int 
originalDataNode, int regionId) {
     dataNodes.stream()
         .filter(dataNode -> dataNode != originalDataNode)
@@ -467,12 +634,35 @@ public class IoTDBRegionMigrateReliabilityITFramework {
     LOGGER.info("Peer clear");
   }
 
+  private static void checkPeerClearIfNodeAlive(
+      int checkTargetDataNode, int originalDataNode, int regionId) {
+    if 
(EnvFactory.getEnv().dataNodeIdToWrapper(checkTargetDataNode).get().isAlive()) {
+      checkPeerClear(checkTargetDataNode, originalDataNode, regionId);
+    }
+  }
+
   private static void checkPeerClear(int checkTargetDataNode, int 
originalDataNode, int regionId) {
     File expectDeletedFile =
         new File(buildConfigurationDataFilePath(checkTargetDataNode, 
originalDataNode, regionId));
     Assert.assertFalse(
         "configuration file should be deleted, but it didn't: " + 
expectDeletedFile.getPath(),
         expectDeletedFile.exists());
+    LOGGER.info("configuration file has been deleted: {}", 
expectDeletedFile.getPath());
+  }
+
+  private void checkClusterStillWritable() {
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      statement.execute(INSERTION2);
+      ResultSet resultSet = statement.executeQuery(COUNT_TIMESERIES);
+      resultSet.next();
+      Assert.assertEquals(2, resultSet.getLong(1));
+      Assert.assertEquals(2, resultSet.getLong(2));
+      LOGGER.info("Region group is still writable");
+    } catch (SQLException e) {
+      LOGGER.error("Something wrong", e);
+      Assert.fail("Something wrong");
+    }
   }
 
   private static String buildRegionDirPath(int dataNode) {
@@ -488,12 +678,26 @@ public class IoTDBRegionMigrateReliabilityITFramework {
         + IoTDBConstant.DATA_REGION_FOLDER_NAME;
   }
 
+  private static String buildDataPath(int dataNode, boolean isSequence) {
+    String nodePath = 
EnvFactory.getEnv().dataNodeIdToWrapper(dataNode).get().getNodePath();
+    return nodePath
+        + File.separator
+        + IoTDBConstant.DATA_FOLDER_NAME
+        + File.separator
+        + "datanode"
+        + File.separator
+        + IoTDBConstant.DATA_FOLDER_NAME
+        + File.separator
+        + (isSequence ? IoTDBConstant.SEQUENCE_FOLDER_NAME : 
IoTDBConstant.UNSEQUENCE_FOLDER_NAME);
+  }
+
   private static String buildConfigurationDataFilePath(
       int localDataNodeId, int remoteDataNodeId, int regionId) {
     String configurationDatDirName =
         buildRegionDirPath(localDataNodeId) + File.separator + "1_" + regionId;
     String expectDeletedFileName =
-        
IoTConsensusServerImpl.generateConfigurationDatFileName(remoteDataNodeId);
+        IoTConsensusServerImpl.generateConfigurationDatFileName(
+            remoteDataNodeId, CONFIGURATION_FILE_NAME);
     return configurationDatDirName + File.separator + expectDeletedFileName;
   }
 
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/KillPointContext.java
similarity index 61%
copy from 
iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
copy to 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/KillPointContext.java
index 385ecaa89fc..d22b6dc1528 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/KillPointContext.java
@@ -17,15 +17,25 @@
  * under the License.
  */
 
-package org.apache.iotdb.consensus.exception;
+package org.apache.iotdb.confignode.it.regionmigration;
 
-public class ConsensusException extends Exception {
+import org.apache.iotdb.it.env.cluster.env.AbstractEnv;
+import org.apache.iotdb.it.env.cluster.node.AbstractNodeWrapper;
 
-  public ConsensusException(String message) {
-    super(message);
+public class KillPointContext {
+  AbstractNodeWrapper nodeWrapper;
+  AbstractEnv env;
+
+  public KillPointContext(AbstractNodeWrapper nodeWrapper, AbstractEnv env) {
+    this.nodeWrapper = nodeWrapper;
+    this.env = env;
+  }
+
+  public AbstractNodeWrapper getNodeWrapper() {
+    return nodeWrapper;
   }
 
-  public ConsensusException(String message, Throwable cause) {
-    super(message, cause);
+  public AbstractEnv getEnv() {
+    return env;
   }
 }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateClusterCrashIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateClusterCrashIT.java
new file mode 100644
index 00000000000..db8ad76e491
--- /dev/null
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateClusterCrashIT.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.confignode.it.regionmigration.pass;
+
+import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateReliabilityITFramework;
+import org.apache.iotdb.confignode.procedure.state.AddRegionPeerState;
+import org.apache.iotdb.confignode.procedure.state.RegionTransitionState;
+import org.apache.iotdb.confignode.procedure.state.RemoveRegionPeerState;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(IoTDBTestRunner.class)
+public class IoTDBRegionMigrateClusterCrashIT extends 
IoTDBRegionMigrateReliabilityITFramework {
+
+  @Test
+  public void clusterCrash1() throws Exception {
+    killClusterTest(buildSet(AddRegionPeerState.CREATE_NEW_REGION_PEER), true);
+  }
+
+  @Test
+  public void clusterCrash2() throws Exception {
+    killClusterTest(buildSet(AddRegionPeerState.DO_ADD_REGION_PEER), false);
+  }
+
+  @Test
+  public void clusterCrash3() throws Exception {
+    killClusterTest(buildSet(AddRegionPeerState.UPDATE_REGION_LOCATION_CACHE), 
true);
+  }
+
+  @Test
+  public void clusterCrash4() throws Exception {
+    killClusterTest(buildSet(RegionTransitionState.CHANGE_REGION_LEADER), 
true);
+  }
+
+  @Test
+  public void clusterCrash6() throws Exception {
+    killClusterTest(buildSet(RemoveRegionPeerState.REMOVE_REGION_PEER), true);
+  }
+
+  @Test
+  public void clusterCrash7() throws Exception {
+    killClusterTest(buildSet(RemoveRegionPeerState.DELETE_OLD_REGION_PEER), 
true);
+  }
+
+  @Test
+  public void clusterCrash8() throws Exception {
+    
killClusterTest(buildSet(RemoveRegionPeerState.REMOVE_REGION_LOCATION_CACHE), 
true);
+  }
+}
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateConfigNodeCrashIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateConfigNodeCrashIT.java
index 5b21cc81bb1..d9bb2acf2d8 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateConfigNodeCrashIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateConfigNodeCrashIT.java
@@ -19,61 +19,119 @@
 
 package org.apache.iotdb.confignode.it.regionmigration.pass;
 
+import org.apache.iotdb.commons.utils.KillPoint.KillNode;
 import org.apache.iotdb.commons.utils.KillPoint.KillPoint;
 import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateReliabilityITFramework;
 import org.apache.iotdb.confignode.procedure.state.AddRegionPeerState;
 import org.apache.iotdb.confignode.procedure.state.RegionTransitionState;
 import org.apache.iotdb.confignode.procedure.state.RemoveRegionPeerState;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
 
 import org.junit.Ignore;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.Arrays;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 
+@RunWith(IoTDBTestRunner.class)
 public class IoTDBRegionMigrateConfigNodeCrashIT extends 
IoTDBRegionMigrateReliabilityITFramework {
   @Test
   @Ignore
-  public void cnCrashDuringPreCheck() throws Exception {
-    successTest(1, 1, 1, 2, 
buildSet(RegionTransitionState.REGION_MIGRATE_PREPARE), noKillPoints());
+  public void cnCrashDuringPreCheckTest() throws Exception {
+    successTest(
+        1,
+        1,
+        1,
+        2,
+        buildSet(RegionTransitionState.REGION_MIGRATE_PREPARE),
+        noKillPoints(),
+        KillNode.CONFIG_NODE);
   }
 
   @Test
-  public void cnCrashDuringCreatePeer() throws Exception {
-    successTest(1, 1, 1, 2, 
buildSet(AddRegionPeerState.CREATE_NEW_REGION_PEER), noKillPoints());
+  public void cnCrashDuringCreatePeerTest() throws Exception {
+    successTest(
+        1,
+        1,
+        1,
+        2,
+        buildSet(AddRegionPeerState.CREATE_NEW_REGION_PEER),
+        noKillPoints(),
+        KillNode.CONFIG_NODE);
   }
 
   @Test
-  public void cnCrashDuringDoAddPeer() throws Exception {
-    successTest(1, 1, 1, 2, buildSet(AddRegionPeerState.DO_ADD_REGION_PEER), 
noKillPoints());
+  public void testCnCrashDuringDoAddPeer() throws Exception {
+    successTest(
+        1,
+        1,
+        1,
+        2,
+        buildSet(AddRegionPeerState.DO_ADD_REGION_PEER),
+        noKillPoints(),
+        KillNode.CONFIG_NODE);
   }
 
   @Test
-  public void cnCrashDuringUpdateCache() throws Exception {
+  public void cnCrashDuringUpdateCacheTest() throws Exception {
     successTest(
-        1, 1, 1, 2, buildSet(AddRegionPeerState.UPDATE_REGION_LOCATION_CACHE), 
noKillPoints());
+        1,
+        1,
+        1,
+        2,
+        buildSet(AddRegionPeerState.UPDATE_REGION_LOCATION_CACHE),
+        noKillPoints(),
+        KillNode.CONFIG_NODE);
   }
 
   @Test
-  public void cnCrashDuringChangeRegionLeader() throws Exception {
-    successTest(1, 1, 1, 2, 
buildSet(RegionTransitionState.CHANGE_REGION_LEADER), noKillPoints());
+  public void cnCrashDuringChangeRegionLeaderTest() throws Exception {
+    successTest(
+        1,
+        1,
+        1,
+        2,
+        buildSet(RegionTransitionState.CHANGE_REGION_LEADER),
+        noKillPoints(),
+        KillNode.CONFIG_NODE);
   }
 
   @Test
-  public void cnCrashDuringRemoveRegionPeer() throws Exception {
-    successTest(1, 1, 1, 2, 
buildSet(RemoveRegionPeerState.REMOVE_REGION_PEER), noKillPoints());
+  public void cnCrashDuringRemoveRegionPeerTest() throws Exception {
+    successTest(
+        1,
+        1,
+        1,
+        2,
+        buildSet(RemoveRegionPeerState.REMOVE_REGION_PEER),
+        noKillPoints(),
+        KillNode.CONFIG_NODE);
   }
 
   @Test
-  public void cnCrashDuringDeleteOldRegionPeer() throws Exception {
-    successTest(1, 1, 1, 2, 
buildSet(RemoveRegionPeerState.DELETE_OLD_REGION_PEER), noKillPoints());
+  public void cnCrashDuringDeleteOldRegionPeerTest() throws Exception {
+    successTest(
+        1,
+        1,
+        1,
+        2,
+        buildSet(RemoveRegionPeerState.DELETE_OLD_REGION_PEER),
+        noKillPoints(),
+        KillNode.CONFIG_NODE);
   }
 
   @Test
-  public void cnCrashDuringRemoveRegionLocationCache() throws Exception {
+  public void cnCrashDuringRemoveRegionLocationCacheTest() throws Exception {
     successTest(
-        1, 1, 1, 2, 
buildSet(RemoveRegionPeerState.REMOVE_REGION_LOCATION_CACHE), noKillPoints());
+        1,
+        1,
+        1,
+        2,
+        buildSet(RemoveRegionPeerState.REMOVE_REGION_LOCATION_CACHE),
+        noKillPoints(),
+        KillNode.CONFIG_NODE);
   }
 
   @Test
@@ -87,6 +145,6 @@ public class IoTDBRegionMigrateConfigNodeCrashIT extends 
IoTDBRegionMigrateRelia
         Arrays.stream(RemoveRegionPeerState.values())
             .map(KillPoint::enumToString)
             .collect(Collectors.toList()));
-    successTest(1, 1, 1, 2, killConfigNodeKeywords, noKillPoints());
+    successTest(1, 1, 1, 2, killConfigNodeKeywords, noKillPoints(), 
KillNode.CONFIG_NODE);
   }
 }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
index 072530da626..f6e31d08304 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
@@ -19,24 +19,22 @@
 
 package org.apache.iotdb.confignode.it.regionmigration.pass;
 
+import org.apache.iotdb.commons.utils.KillPoint.KillNode;
 import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateReliabilityITFramework;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
-import org.apache.iotdb.itbase.category.ClusterIT;
 
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
 @RunWith(IoTDBTestRunner.class)
-@Category({ClusterIT.class})
 public class IoTDBRegionMigrateNormalIT extends 
IoTDBRegionMigrateReliabilityITFramework {
   @Test
   public void normal1C2DTest() throws Exception {
-    successTest(1, 1, 1, 2, noKillPoints(), noKillPoints());
+    successTest(1, 1, 1, 2, noKillPoints(), noKillPoints(), 
KillNode.ALL_NODES);
   }
 
   @Test
   public void normal3C3DTest() throws Exception {
-    successTest(2, 3, 3, 3, noKillPoints(), noKillPoints());
+    successTest(2, 3, 3, 3, noKillPoints(), noKillPoints(), 
KillNode.ALL_NODES);
   }
 }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateOtherIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateOtherIT.java
index 6d9444c9e4f..f4ca461edd8 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateOtherIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateOtherIT.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.confignode.it.regionmigration.pass;
 
+import org.apache.iotdb.commons.utils.KillPoint.KillNode;
 import org.apache.iotdb.commons.utils.KillPoint.NeverTriggeredKillPoint;
 import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateReliabilityITFramework;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
@@ -36,7 +37,13 @@ public class IoTDBRegionMigrateOtherIT extends 
IoTDBRegionMigrateReliabilityITFr
   public void badKillPoint() throws Exception {
     try {
       successTest(
-          1, 1, 1, 2, 
buildSet(NeverTriggeredKillPoint.NEVER_TRIGGERED_KILL_POINT), noKillPoints());
+          1,
+          1,
+          1,
+          2,
+          buildSet(NeverTriggeredKillPoint.NEVER_TRIGGERED_KILL_POINT),
+          noKillPoints(),
+          KillNode.ALL_NODES);
     } catch (AssertionError e) {
       return;
     }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/notpass/datanodecrash/CoordinatorRemoveRemotePeerCrashIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateCoordinatorCrashWhenRemoveRemotePeerIT.java
similarity index 64%
rename from 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/notpass/datanodecrash/CoordinatorRemoveRemotePeerCrashIT.java
rename to 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateCoordinatorCrashWhenRemoveRemotePeerIT.java
index 7533424909b..5a63e76f979 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/notpass/datanodecrash/CoordinatorRemoveRemotePeerCrashIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateCoordinatorCrashWhenRemoveRemotePeerIT.java
@@ -17,35 +17,37 @@
  * under the License.
  */
 
-package org.apache.iotdb.confignode.it.regionmigration.notpass.datanodecrash;
+package org.apache.iotdb.confignode.it.regionmigration.pass.datanodecrash;
 
-import 
org.apache.iotdb.commons.utils.KillPoint.IoTConsensusRemovePeerKillPoints;
-import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateReliabilityITFramework;
+import 
org.apache.iotdb.commons.utils.KillPoint.IoTConsensusRemovePeerCoordinatorKillPoints;
+import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateDataNodeCrashITFramework;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class CoordinatorRemoveRemotePeerCrashIT extends 
IoTDBRegionMigrateReliabilityITFramework {
-  private <T extends Enum<T>> void base(T... dataNodeKillPoints) throws 
Exception {
-    successTest(1, 1, 1, 2, noKillPoints(), buildSet(dataNodeKillPoints));
-  }
+@RunWith(IoTDBTestRunner.class)
+public class IoTDBRegionMigrateCoordinatorCrashWhenRemoveRemotePeerIT
+    extends IoTDBRegionMigrateDataNodeCrashITFramework {
 
   @Test
   public void initCrash() throws Exception {
-    base(IoTConsensusRemovePeerKillPoints.INIT);
+    success(IoTConsensusRemovePeerCoordinatorKillPoints.INIT);
   }
 
   @Test
   public void crashAfterNotifyPeersToRemoveSyncLogChannel() throws Exception {
-    
base(IoTConsensusRemovePeerKillPoints.AFTER_NOTIFY_PEERS_TO_REMOVE_SYNC_LOG_CHANNEL);
+    success(
+        
IoTConsensusRemovePeerCoordinatorKillPoints.AFTER_NOTIFY_PEERS_TO_REMOVE_SYNC_LOG_CHANNEL);
   }
 
   @Test
   public void crashAfterInactivePeer() throws Exception {
-    base(IoTConsensusRemovePeerKillPoints.AFTER_INACTIVE_PEER);
+    success(IoTConsensusRemovePeerCoordinatorKillPoints.AFTER_INACTIVE_PEER);
   }
 
   @Test
   public void crashAfterFinish() throws Exception {
-    base(IoTConsensusRemovePeerKillPoints.FINISH);
+    success(IoTConsensusRemovePeerCoordinatorKillPoints.FINISH);
   }
 }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/notpass/datanodecrash/IoTDBRegionMigrateDataNodeCrashIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateDataNodeCrashIT.java
similarity index 58%
rename from 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/notpass/datanodecrash/IoTDBRegionMigrateDataNodeCrashIT.java
rename to 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateDataNodeCrashIT.java
index 6b023274aef..a5c619ec704 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/notpass/datanodecrash/IoTDBRegionMigrateDataNodeCrashIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateDataNodeCrashIT.java
@@ -17,9 +17,10 @@
  * under the License.
  */
 
-package org.apache.iotdb.confignode.it.regionmigration.notpass.datanodecrash;
+package org.apache.iotdb.confignode.it.regionmigration.pass.datanodecrash;
 
 import org.apache.iotdb.commons.utils.KillPoint.DataNodeKillPoints;
+import org.apache.iotdb.commons.utils.KillPoint.KillNode;
 import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateReliabilityITFramework;
 
 import org.junit.Test;
@@ -27,15 +28,33 @@ import org.junit.Test;
 public class IoTDBRegionMigrateDataNodeCrashIT extends 
IoTDBRegionMigrateReliabilityITFramework {
   // region Coordinator DataNode crash tests
 
+  private final int dataReplicateFactor = 2;
+  private final int schemaReplicationFactor = 2;
+  private final int configNodeNum = 1;
+  private final int dataNodeNum = 3;
+
   @Test
   public void coordinatorCrashDuringAddPeerTransition() throws Exception {
     failTest(
-        2, 2, 1, 3, noKillPoints(), 
buildSet(DataNodeKillPoints.COORDINATOR_ADD_PEER_TRANSITION));
+        2,
+        2,
+        1,
+        3,
+        noKillPoints(),
+        buildSet(DataNodeKillPoints.COORDINATOR_ADD_PEER_TRANSITION),
+        KillNode.COORDINATOR_DATANODE);
   }
 
   @Test
   public void coordinatorCrashDuringAddPeerDone() throws Exception {
-    failTest(2, 2, 1, 3, noKillPoints(), 
buildSet(DataNodeKillPoints.COORDINATOR_ADD_PEER_DONE));
+    failTest(
+        2,
+        2,
+        1,
+        3,
+        noKillPoints(),
+        buildSet(DataNodeKillPoints.COORDINATOR_ADD_PEER_DONE),
+        KillNode.COORDINATOR_DATANODE);
   }
 
   // endregion ----------------------------------------------
@@ -44,7 +63,14 @@ public class IoTDBRegionMigrateDataNodeCrashIT extends 
IoTDBRegionMigrateReliabi
 
   @Test
   public void originalCrashDuringAddPeerDone() throws Exception {
-    failTest(2, 2, 1, 3, noKillPoints(), 
buildSet(DataNodeKillPoints.ORIGINAL_ADD_PEER_DONE));
+    failTest(
+        2,
+        2,
+        1,
+        3,
+        noKillPoints(),
+        buildSet(DataNodeKillPoints.ORIGINAL_ADD_PEER_DONE),
+        KillNode.ORIGINAL_DATANODE);
   }
 
   // endregion ----------------------------------------------
@@ -54,18 +80,37 @@ public class IoTDBRegionMigrateDataNodeCrashIT extends 
IoTDBRegionMigrateReliabi
   @Test
   public void destinationCrashDuringCreateLocalPeer() throws Exception {
     failTest(
-        2, 2, 1, 3, noKillPoints(), 
buildSet(DataNodeKillPoints.DESTINATION_CREATE_LOCAL_PEER));
+        2,
+        2,
+        1,
+        3,
+        noKillPoints(),
+        buildSet(DataNodeKillPoints.DESTINATION_CREATE_LOCAL_PEER),
+        KillNode.DESTINATION_DATANODE);
   }
 
   @Test
   public void destinationCrashDuringAddPeerTransition() throws Exception {
     failTest(
-        2, 2, 1, 3, noKillPoints(), 
buildSet(DataNodeKillPoints.DESTINATION_ADD_PEER_TRANSITION));
+        2,
+        2,
+        1,
+        3,
+        noKillPoints(),
+        buildSet(DataNodeKillPoints.DESTINATION_ADD_PEER_TRANSITION),
+        KillNode.DESTINATION_DATANODE);
   }
 
   @Test
   public void destinationCrashDuringAddPeerDone() throws Exception {
-    failTest(2, 2, 1, 3, noKillPoints(), 
buildSet(DataNodeKillPoints.DESTINATION_ADD_PEER_DONE));
+    failTest(
+        2,
+        2,
+        1,
+        3,
+        noKillPoints(),
+        buildSet(DataNodeKillPoints.DESTINATION_ADD_PEER_DONE),
+        KillNode.DESTINATION_DATANODE);
   }
 
   // endregion ----------------------------------------------
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateOriginalCrashWhenDeleteLocalPeerIT.java
similarity index 65%
copy from 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
copy to 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateOriginalCrashWhenDeleteLocalPeerIT.java
index 072530da626..a21884b5da2 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateOriginalCrashWhenDeleteLocalPeerIT.java
@@ -17,26 +17,25 @@
  * under the License.
  */
 
-package org.apache.iotdb.confignode.it.regionmigration.pass;
+package org.apache.iotdb.confignode.it.regionmigration.pass.datanodecrash;
 
-import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateReliabilityITFramework;
+import 
org.apache.iotdb.commons.utils.KillPoint.IoTConsensusDeleteLocalPeerKillPoints;
+import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateDataNodeCrashITFramework;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
-import org.apache.iotdb.itbase.category.ClusterIT;
 
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
 @RunWith(IoTDBTestRunner.class)
-@Category({ClusterIT.class})
-public class IoTDBRegionMigrateNormalIT extends 
IoTDBRegionMigrateReliabilityITFramework {
+public class IoTDBRegionMigrateOriginalCrashWhenDeleteLocalPeerIT
+    extends IoTDBRegionMigrateDataNodeCrashITFramework {
   @Test
-  public void normal1C2DTest() throws Exception {
-    successTest(1, 1, 1, 2, noKillPoints(), noKillPoints());
+  public void crashBeforeDelete() throws Exception {
+    success(IoTConsensusDeleteLocalPeerKillPoints.BEFORE_DELETE);
   }
 
   @Test
-  public void normal3C3DTest() throws Exception {
-    successTest(2, 3, 3, 3, noKillPoints(), noKillPoints());
+  public void crashAfterDelete() throws Exception {
+    success(IoTConsensusDeleteLocalPeerKillPoints.AFTER_DELETE);
   }
 }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateOriginalCrashWhenRemoveRemotePeerIT.java
similarity index 64%
copy from 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
copy to 
integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateOriginalCrashWhenRemoveRemotePeerIT.java
index 072530da626..cf6e0eb19e6 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/IoTDBRegionMigrateNormalIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/datanodecrash/IoTDBRegionMigrateOriginalCrashWhenRemoveRemotePeerIT.java
@@ -17,26 +17,25 @@
  * under the License.
  */
 
-package org.apache.iotdb.confignode.it.regionmigration.pass;
+package org.apache.iotdb.confignode.it.regionmigration.pass.datanodecrash;
 
-import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateReliabilityITFramework;
+import 
org.apache.iotdb.commons.utils.KillPoint.IoTConsensusInactivatePeerKillPoints;
+import 
org.apache.iotdb.confignode.it.regionmigration.IoTDBRegionMigrateDataNodeCrashITFramework;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
-import org.apache.iotdb.itbase.category.ClusterIT;
 
 import org.junit.Test;
-import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
 @RunWith(IoTDBTestRunner.class)
-@Category({ClusterIT.class})
-public class IoTDBRegionMigrateNormalIT extends 
IoTDBRegionMigrateReliabilityITFramework {
+public class IoTDBRegionMigrateOriginalCrashWhenRemoveRemotePeerIT
+    extends IoTDBRegionMigrateDataNodeCrashITFramework {
   @Test
-  public void normal1C2DTest() throws Exception {
-    successTest(1, 1, 1, 2, noKillPoints(), noKillPoints());
+  public void crashBeforeInactivate() throws Exception {
+    success(IoTConsensusInactivatePeerKillPoints.BEFORE_INACTIVATE);
   }
 
   @Test
-  public void normal3C3DTest() throws Exception {
-    successTest(2, 3, 3, 3, noKillPoints(), noKillPoints());
+  public void crashAfterInactivate() throws Exception {
+    success(IoTConsensusInactivatePeerKillPoints.AFTER_INACTIVATE);
   }
 }
diff --git 
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TElasticFramedTransport.java
 
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TElasticFramedTransport.java
index 1075e1de865..b0c55c21bd0 100644
--- 
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TElasticFramedTransport.java
+++ 
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TElasticFramedTransport.java
@@ -178,8 +178,7 @@ public class TElasticFramedTransport extends TTransport {
   @Override
   public int getBytesRemainingInBuffer() {
     // return -1 can make the caller protocol to copy binary data from the 
underlying transport.
-    if (copyBinary) return -1;
-    return readBuffer.getBytesRemainingInBuffer();
+    return copyBinary ? -1 : readBuffer.getBytesRemainingInBuffer();
   }
 
   @Override
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/AsyncDataNodeClientPool.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/AsyncDataNodeClientPool.java
index 35cd65fceeb..e52367276c8 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/AsyncDataNodeClientPool.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/AsyncDataNodeClientPool.java
@@ -74,6 +74,7 @@ import 
org.apache.iotdb.mpp.rpc.thrift.TPushSingleTopicMetaReq;
 import org.apache.iotdb.mpp.rpc.thrift.TPushTopicMetaReq;
 import org.apache.iotdb.mpp.rpc.thrift.TRegionLeaderChangeReq;
 import org.apache.iotdb.mpp.rpc.thrift.TRegionRouteReq;
+import org.apache.iotdb.mpp.rpc.thrift.TResetPeerListReq;
 import org.apache.iotdb.mpp.rpc.thrift.TRollbackSchemaBlackListReq;
 import org.apache.iotdb.mpp.rpc.thrift.TRollbackSchemaBlackListWithTemplateReq;
 import org.apache.iotdb.mpp.rpc.thrift.TRollbackViewSchemaBlackListReq;
@@ -484,6 +485,12 @@ public class AsyncDataNodeClientPool {
               (AsyncTSStatusRPCHandler)
                   clientHandler.createAsyncRPCHandler(requestId, 
targetDataNode));
           break;
+        case RESET_PEER_LIST:
+          client.resetPeerList(
+              (TResetPeerListReq) clientHandler.getRequest(requestId),
+              (AsyncTSStatusRPCHandler)
+                  clientHandler.createAsyncRPCHandler(requestId, 
targetDataNode));
+          break;
         default:
           LOGGER.error(
               "Unexpected DataNode Request Type: {} when 
sendAsyncRequestToDataNode",
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/handlers/AsyncClientHandler.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/handlers/AsyncClientHandler.java
index 4f05f892afc..a8c445665d0 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/handlers/AsyncClientHandler.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/handlers/AsyncClientHandler.java
@@ -266,6 +266,7 @@ public class AsyncClientHandler<Q, R> {
       case UPDATE_TEMPLATE:
       case CHANGE_REGION_LEADER:
       case KILL_QUERY_INSTANCE:
+      case RESET_PEER_LIST:
       default:
         return new AsyncTSStatusRPCHandler(
             requestType,
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
index 4e4ed126f68..f5898d4bc17 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
@@ -654,7 +654,14 @@ public class ProcedureManager {
     // select coordinator for adding peer
     RegionMaintainHandler handler = new RegionMaintainHandler(configManager);
     final TDataNodeLocation coordinatorForAddPeer =
-        handler.filterDataNodeWithOtherRegionReplica(regionGroupId, 
destDataNode).orElse(null);
+        handler
+            .filterDataNodeWithOtherRegionReplica(
+                regionGroupId,
+                destDataNode,
+                NodeStatus.Running,
+                NodeStatus.Removing,
+                NodeStatus.ReadOnly)
+            .orElse(null);
     // Select coordinator for removing peer
     // For now, destDataNode temporarily acts as the coordinatorForRemovePeer
     final TDataNodeLocation coordinatorForRemovePeer = destDataNode;
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/Procedure.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/Procedure.java
index 1008fe62dfd..f0a6378aefb 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/Procedure.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/Procedure.java
@@ -51,11 +51,6 @@ public abstract class Procedure<Env> implements 
Comparable<Procedure<Env>> {
   private static final Logger LOG = LoggerFactory.getLogger(Procedure.class);
   public static final long NO_PROC_ID = -1;
   public static final long NO_TIMEOUT = -1;
-  /**
-   * The isDeserialized of a newly created procedure is false. When a leader 
switch or ConfigNode
-   * restart occurs during the execution of the procedure, isDeserialized 
becomes true.
-   */
-  private boolean isDeserialized = false;
 
   private long parentProcId = NO_PROC_ID;
   private long rootProcId = NO_PROC_ID;
@@ -192,8 +187,6 @@ public abstract class Procedure<Env> implements 
Comparable<Procedure<Env>> {
   public void deserialize(ByteBuffer byteBuffer) {
     // procid
     this.setProcId(byteBuffer.getLong());
-    // isDeserialized
-    this.setDeserialized(true);
     // state
     this.setState(ProcedureState.values()[byteBuffer.getInt()]);
     //  submit time
@@ -545,10 +538,6 @@ public abstract class Procedure<Env> implements 
Comparable<Procedure<Env>> {
     return procId;
   }
 
-  public boolean isDeserialized() {
-    return isDeserialized;
-  }
-
   public boolean hasParent() {
     return parentProcId != NO_PROC_ID;
   }
@@ -574,10 +563,6 @@ public abstract class Procedure<Env> implements 
Comparable<Procedure<Env>> {
     this.procId = procId;
   }
 
-  private void setDeserialized(boolean isDeserialized) {
-    this.isDeserialized = isDeserialized;
-  }
-
   public void setProcRunnable() {
     this.submittedTime = System.currentTimeMillis();
     setState(ProcedureState.RUNNABLE);
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/RegionMaintainHandler.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/RegionMaintainHandler.java
index b9ccd7e3418..64282e0e3ff 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/RegionMaintainHandler.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/RegionMaintainHandler.java
@@ -34,6 +34,8 @@ import org.apache.iotdb.commons.cluster.NodeStatus;
 import org.apache.iotdb.commons.service.metric.MetricService;
 import org.apache.iotdb.commons.utils.NodeUrlUtils;
 import org.apache.iotdb.confignode.client.DataNodeRequestType;
+import org.apache.iotdb.confignode.client.async.AsyncDataNodeClientPool;
+import org.apache.iotdb.confignode.client.async.handlers.AsyncClientHandler;
 import org.apache.iotdb.confignode.client.sync.SyncDataNodeClientPool;
 import org.apache.iotdb.confignode.conf.ConfigNodeConfig;
 import org.apache.iotdb.confignode.conf.ConfigNodeDescriptor;
@@ -60,6 +62,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -249,7 +252,7 @@ public class RegionMaintainHandler {
    * @param regionId region id
    * @return TSStatus
    */
-  public TSStatus addRegionPeer(
+  public TSStatus submitAddRegionPeerTask(
       long procedureId,
       TDataNodeLocation destDataNode,
       TConsensusGroupId regionId,
@@ -266,11 +269,12 @@ public class RegionMaintainHandler {
                 maintainPeerReq,
                 DataNodeRequestType.ADD_REGION_PEER);
     LOGGER.info(
-        "{}, Send action addRegionPeer finished, regionId: {}, rpcDataNode: 
{},  destDataNode: {}",
+        "{}, Send action addRegionPeer finished, regionId: {}, rpcDataNode: 
{},  destDataNode: {}, status: {}",
         REGION_MIGRATE_PROCESS,
         regionId,
         getIdWithRpcEndpoint(coordinator),
-        getIdWithRpcEndpoint(destDataNode));
+        getIdWithRpcEndpoint(destDataNode),
+        status);
     return status;
   }
 
@@ -284,7 +288,7 @@ public class RegionMaintainHandler {
    * @param regionId region id
    * @return TSStatus
    */
-  public TSStatus removeRegionPeer(
+  public TSStatus submitRemoveRegionPeerTask(
       long procedureId,
       TDataNodeLocation originalDataNode,
       TConsensusGroupId regionId,
@@ -318,7 +322,7 @@ public class RegionMaintainHandler {
    * @param regionId region id
    * @return TSStatus
    */
-  public TSStatus deleteOldRegionPeer(
+  public TSStatus submitDeleteOldRegionPeerTask(
       long procedureId, TDataNodeLocation originalDataNode, TConsensusGroupId 
regionId) {
 
     TSStatus status;
@@ -348,27 +352,43 @@ public class RegionMaintainHandler {
   }
 
   public TSStatus resetPeerList(
-      TConsensusGroupId regionId, List<TDataNodeLocation> 
correctDataNodeLocations) {
-    Optional<TDataNodeLocation> optional = 
filterDataNodeWithOtherRegionReplica(regionId, null);
-    TDataNodeLocation selectDataNode = optional.get();
+      TConsensusGroupId regionId,
+      List<TDataNodeLocation> correctDataNodeLocations,
+      TDataNodeLocation target) {
     TSStatus status =
         SyncDataNodeClientPool.getInstance()
             .sendSyncRequestToDataNodeWithRetry(
-                selectDataNode.getInternalEndPoint(),
+                target.getInternalEndPoint(),
                 new TResetPeerListReq(regionId, correctDataNodeLocations),
                 DataNodeRequestType.RESET_PEER_LIST);
     return status;
   }
 
+  public Map<Integer, TSStatus> resetPeerList(
+      TConsensusGroupId regionId,
+      List<TDataNodeLocation> correctDataNodeLocations,
+      Map<Integer, TDataNodeLocation> dataNodeLocationMap) {
+    AsyncClientHandler<TResetPeerListReq, TSStatus> clientHandler =
+        new AsyncClientHandler<>(
+            DataNodeRequestType.RESET_PEER_LIST,
+            new TResetPeerListReq(regionId, correctDataNodeLocations),
+            dataNodeLocationMap);
+    
AsyncDataNodeClientPool.getInstance().sendAsyncRequestToDataNodeWithRetry(clientHandler);
+    return clientHandler.getResponseMap();
+  }
+
   // TODO: will use 'procedure yield' to refactor later
   public TRegionMigrateResult waitTaskFinish(long taskId, TDataNodeLocation 
dataNodeLocation) {
-    long lastTimeConnectDataNode = System.currentTimeMillis();
-    while 
(configManager.getLoadManager().getNodeStatus(dataNodeLocation.getDataNodeId())
-        != NodeStatus.Unknown) {
+    // In some cases the DataNode is still working, but its status is unknown.
+    // In order to make task continue under this circumstance, some 
unconditional retries are
+    // performed here.
+    int unconditionallyRetry = 0;
+    while (unconditionallyRetry < 6
+        || 
configManager.getLoadManager().getNodeStatus(dataNodeLocation.getDataNodeId())
+            != NodeStatus.Unknown) {
       try (SyncDataNodeInternalServiceClient dataNodeClient =
           
dataNodeClientManager.borrowClient(dataNodeLocation.getInternalEndPoint())) {
         TRegionMigrateResult report = 
dataNodeClient.getRegionMaintainResult(taskId);
-        lastTimeConnectDataNode = System.currentTimeMillis();
         if (report.getTaskStatus() != TRegionMaintainTaskStatus.PROCESSING) {
           return report;
         }
@@ -381,6 +401,7 @@ public class RegionMaintainHandler {
           Thread.currentThread().interrupt();
         }
       }
+      unconditionallyRetry++;
     }
     LOGGER.warn(
         "{} task {} cannot contact to DataNode {}",
@@ -395,10 +416,6 @@ public class RegionMaintainHandler {
   }
 
   public void addRegionLocation(TConsensusGroupId regionId, TDataNodeLocation 
newLocation) {
-    LOGGER.info(
-        "AddRegionLocation started, add region {} to {}",
-        regionId,
-        getIdWithRpcEndpoint(newLocation));
     AddRegionLocationPlan req = new AddRegionLocationPlan(regionId, 
newLocation);
     TSStatus status = 
configManager.getPartitionManager().addRegionLocation(req);
     LOGGER.info(
@@ -406,31 +423,28 @@ public class RegionMaintainHandler {
         regionId,
         getIdWithRpcEndpoint(newLocation),
         status);
-
-    // Remove the RegionGroupCache of the regionId
-    configManager.getLoadManager().removeRegionGroupCache(regionId);
-
-    // Broadcast the latest RegionRouteMap when Region migration finished
-    configManager.getLoadManager().broadcastLatestRegionRouteMap();
+    updateRegionLocation(regionId);
   }
 
   public void removeRegionLocation(
       TConsensusGroupId regionId, TDataNodeLocation deprecatedLocation) {
-    LOGGER.info(
-        "RemoveRegionLocation started, remove region {} from DataNode {}",
-        regionId,
-        getIdWithRpcEndpoint(deprecatedLocation));
     RemoveRegionLocationPlan req = new RemoveRegionLocationPlan(regionId, 
deprecatedLocation);
     TSStatus status = 
configManager.getPartitionManager().removeRegionLocation(req);
     LOGGER.info(
-        "RemoveRegionLocation finished, remove region {} from DataNode {}, 
result is {}",
+        "RemoveRegionLocation remove region {} from DataNode {}, result is {}",
         regionId,
         getIdWithRpcEndpoint(deprecatedLocation),
         status);
+    updateRegionLocation(regionId);
+  }
 
+  private void updateRegionLocation(TConsensusGroupId regionId) {
     // Remove the RegionGroupCache of the regionId
     configManager.getLoadManager().removeRegionGroupCache(regionId);
-
+    // force balance region leader to skip waiting for leader election
+    configManager.getLoadManager().forceBalanceRegionLeader();
+    // Wait for leader election
+    
configManager.getLoadManager().waitForLeaderElection(Collections.singletonList(regionId));
     // Broadcast the latest RegionRouteMap when Region migration finished
     configManager.getLoadManager().broadcastLatestRegionRouteMap();
   }
@@ -699,6 +713,12 @@ public class RegionMaintainHandler {
    */
   public Optional<TDataNodeLocation> filterDataNodeWithOtherRegionReplica(
       TConsensusGroupId regionId, TDataNodeLocation filterLocation) {
+    return filterDataNodeWithOtherRegionReplica(
+        regionId, filterLocation, NodeStatus.Running, NodeStatus.ReadOnly);
+  }
+
+  public Optional<TDataNodeLocation> filterDataNodeWithOtherRegionReplica(
+      TConsensusGroupId regionId, TDataNodeLocation filterLocation, 
NodeStatus... allowingStatus) {
     List<TDataNodeLocation> regionLocations = findRegionLocations(regionId);
     if (regionLocations.isEmpty()) {
       LOGGER.warn("Cannot find DataNodes contain the given region: {}", 
regionId);
@@ -708,15 +728,10 @@ public class RegionMaintainHandler {
     // Choosing the RUNNING DataNodes to execute firstly
     // If all DataNodes are not RUNNING, then choose the REMOVING DataNodes 
secondly
     List<TDataNodeLocation> aliveDataNodes =
-        
configManager.getNodeManager().filterDataNodeThroughStatus(NodeStatus.Running).stream()
+        
configManager.getNodeManager().filterDataNodeThroughStatus(allowingStatus).stream()
             .map(TDataNodeConfiguration::getLocation)
             .collect(Collectors.toList());
 
-    aliveDataNodes.addAll(
-        
configManager.getNodeManager().filterDataNodeThroughStatus(NodeStatus.Removing).stream()
-            .map(TDataNodeConfiguration::getLocation)
-            .collect(Collectors.toList()));
-
     // TODO return the node which has lowest load.
     for (TDataNodeLocation aliveDataNode : aliveDataNodes) {
       if (regionLocations.contains(aliveDataNode) && 
!aliveDataNode.equals(filterLocation)) {
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/StateMachineProcedure.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/StateMachineProcedure.java
index b29d5034915..87743003ff0 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/StateMachineProcedure.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/StateMachineProcedure.java
@@ -67,6 +67,8 @@ public abstract class StateMachineProcedure<Env, TState> 
extends Procedure<Env>
   /** Mark whether this procedure is called by a pipe forwarded request. */
   protected boolean isGeneratedByPipe;
 
+  private boolean stateDeserialized = false;
+
   protected StateMachineProcedure() {
     this(false);
   }
@@ -191,6 +193,7 @@ public abstract class StateMachineProcedure<Env, TState> 
extends Procedure<Env>
 
       LOG.trace("{}", this);
       stateFlow = executeFromState(env, state);
+      setStateDeserialized(false);
       if (!hasMoreState()) {
         setNextState(EOF_STATE);
       }
@@ -334,5 +337,20 @@ public abstract class StateMachineProcedure<Env, TState> 
extends Procedure<Env>
     } else {
       states = null;
     }
+    this.setStateDeserialized(true);
+  }
+
+  /**
+   * The isStateDeserialized indicates whether the current stage of this 
procedure was generated by
+   * deserialization. If true, this means the procedure has undergone a leader 
switch or a restart
+   * recovery at this stage. After the procedure is recovered, you may not 
want to re-execute all
+   * the code in this stage, which is the purpose of this variable.
+   */
+  public boolean isStateDeserialized() {
+    return stateDeserialized;
+  }
+
+  private void setStateDeserialized(boolean isDeserialized) {
+    this.stateDeserialized = isDeserialized;
   }
 }
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/AddRegionPeerProcedure.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/AddRegionPeerProcedure.java
index 853262625b7..9cefb239489 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/AddRegionPeerProcedure.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/AddRegionPeerProcedure.java
@@ -40,6 +40,11 @@ import org.slf4j.LoggerFactory;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static org.apache.iotdb.commons.utils.KillPoint.KillPoint.setKillPoint;
 import static 
org.apache.iotdb.confignode.procedure.state.AddRegionPeerState.UPDATE_REGION_LOCATION_CACHE;
@@ -79,39 +84,35 @@ public class AddRegionPeerProcedure
       outerSwitch:
       switch (state) {
         case CREATE_NEW_REGION_PEER:
-          handler.createNewRegionPeer(consensusGroupId, destDataNode);
+          TSStatus status = handler.createNewRegionPeer(consensusGroupId, 
destDataNode);
           setKillPoint(state);
+          if (status.getCode() != SUCCESS_STATUS.getStatusCode()) {
+            rollback(env, handler);
+          }
           setNextState(AddRegionPeerState.DO_ADD_REGION_PEER);
           break;
         case DO_ADD_REGION_PEER:
-          TSStatus tsStatus =
-              handler.addRegionPeer(this.getProcId(), destDataNode, 
consensusGroupId, coordinator);
-          setKillPoint(state);
-          TRegionMigrateResult result;
-          if (tsStatus.getCode() == SUCCESS_STATUS.getStatusCode()) {
-            result = handler.waitTaskFinish(this.getProcId(), coordinator);
-          } else {
-            throw new ProcedureException("ADD_REGION_PEER executed failed in 
DataNode");
+          // We don't want to re-submit AddRegionPeerTask when leader change 
or ConfigNode reboot
+          if (!this.isStateDeserialized()) {
+            TSStatus tsStatus =
+                handler.submitAddRegionPeerTask(
+                    this.getProcId(), destDataNode, consensusGroupId, 
coordinator);
+            setKillPoint(state);
+            if (tsStatus.getCode() != SUCCESS_STATUS.getStatusCode()) {
+              throw new ProcedureException("ADD_REGION_PEER executed failed in 
DataNode");
+            }
           }
+          TRegionMigrateResult result = 
handler.waitTaskFinish(this.getProcId(), coordinator);
           switch (result.getTaskStatus()) {
             case TASK_NOT_EXIST:
               // coordinator crashed and lost its task table
             case FAIL:
               // maybe some DataNode crash
               LOGGER.warn(
-                  "result is {}, will use resetPeerList to clean in the 
future",
+                  "{} result is {}, procedure failed. Will try to reset peer 
list automatically...",
+                  state,
                   result.getTaskStatus());
-              //              List<TDataNodeLocation> correctDataNodeLocations 
=
-              //
-              // 
env.getConfigManager().getPartitionManager().getAllReplicaSets().stream()
-              //                      .filter(
-              //                          tRegionReplicaSet ->
-              //
-              // tRegionReplicaSet.getRegionId().equals(consensusGroupId))
-              //                      .findAny()
-              //                      .get()
-              //                      .getDataNodeLocations();
-              //              handler.resetPeerList(consensusGroupId, 
correctDataNodeLocations);
+              rollback(env, handler);
               return Flow.NO_MORE_STATE;
             case PROCESSING:
               // should never happen
@@ -145,6 +146,54 @@ public class AddRegionPeerProcedure
     return Flow.HAS_MORE_STATE;
   }
 
+  private void rollback(ConfigNodeProcedureEnv env, RegionMaintainHandler 
handler) {
+    List<TDataNodeLocation> correctDataNodeLocations =
+        
env.getConfigManager().getPartitionManager().getAllReplicaSets().stream()
+            .filter(tRegionReplicaSet -> 
tRegionReplicaSet.getRegionId().equals(consensusGroupId))
+            .findAny()
+            .get()
+            .getDataNodeLocations();
+
+    String correctStr =
+        correctDataNodeLocations.stream()
+            .map(TDataNodeLocation::getDataNodeId)
+            .collect(Collectors.toList())
+            .toString();
+    List<TDataNodeLocation> relatedDataNodeLocations = new 
ArrayList<>(correctDataNodeLocations);
+    relatedDataNodeLocations.add(destDataNode);
+    Map<Integer, TDataNodeLocation> relatedDataNodeLocationMap = new 
HashMap<>();
+    relatedDataNodeLocations.forEach(
+        location -> relatedDataNodeLocationMap.put(location.dataNodeId, 
location));
+    LOGGER.info(
+        "Will reset peer list of consensus group {} on DataNode {}",
+        consensusGroupId,
+        relatedDataNodeLocations.stream()
+            .map(TDataNodeLocation::getDataNodeId)
+            .collect(Collectors.toList()));
+
+    Map<Integer, TSStatus> resultMap =
+        handler.resetPeerList(
+            consensusGroupId, correctDataNodeLocations, 
relatedDataNodeLocationMap);
+
+    resultMap.forEach(
+        (dataNodeId, resetResult) -> {
+          if (resetResult.getCode() == SUCCESS_STATUS.getStatusCode()) {
+            LOGGER.info(
+                "reset peer list: peer list of consensus group {} on DataNode 
{} has been successfully to {}",
+                consensusGroupId,
+                dataNodeId,
+                correctStr);
+          } else {
+            // TODO: more precise
+            LOGGER.warn(
+                "reset peer list: peer list of consensus group {} on DataNode 
{} failed to reset to {}, you may manually reset it",
+                consensusGroupId,
+                dataNodeId,
+                correctStr);
+          }
+        });
+  }
+
   @Override
   protected void rollbackState(
       ConfigNodeProcedureEnv configNodeProcedureEnv, AddRegionPeerState 
addRegionPeerState)
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionPeerProcedure.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionPeerProcedure.java
index 7055a274874..1e183a631e6 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionPeerProcedure.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionPeerProcedure.java
@@ -80,30 +80,41 @@ public class RemoveRegionPeerProcedure
       switch (state) {
         case REMOVE_REGION_PEER:
           tsStatus =
-              handler.removeRegionPeer(
+              handler.submitRemoveRegionPeerTask(
                   this.getProcId(), targetDataNode, consensusGroupId, 
coordinator);
           setKillPoint(state);
           if (tsStatus.getCode() != SUCCESS_STATUS.getStatusCode()) {
-            throw new ProcedureException("REMOVE_REGION_PEER executed failed 
in DataNode");
+            LOGGER.warn(
+                "{} task submitted failed, procedure will continue. You should 
manually clear peer list.",
+                state);
+            setNextState(DELETE_OLD_REGION_PEER);
+            break;
           }
           TRegionMigrateResult removeRegionPeerResult =
               handler.waitTaskFinish(this.getProcId(), coordinator);
           if (removeRegionPeerResult.getTaskStatus() != 
TRegionMaintainTaskStatus.SUCCESS) {
-            throw new ProcedureException("REMOVE_REGION_PEER executed failed 
in DataNode");
+            LOGGER.warn(
+                "{} executed failed, procedure will continue. You should 
manually clear peer list.",
+                state);
           }
           setNextState(DELETE_OLD_REGION_PEER);
           break;
         case DELETE_OLD_REGION_PEER:
           tsStatus =
-              handler.deleteOldRegionPeer(this.getProcId(), targetDataNode, 
consensusGroupId);
+              handler.submitDeleteOldRegionPeerTask(
+                  this.getProcId(), targetDataNode, consensusGroupId);
           setKillPoint(state);
           if (tsStatus.getCode() != SUCCESS_STATUS.getStatusCode()) {
-            throw new ProcedureException("DELETE_OLD_REGION_PEER executed 
failed in DataNode");
+            LOGGER.warn(
+                "DELETE_OLD_REGION_PEER task submitted failed, procedure will 
continue. You should manually delete region file.");
+            setNextState(REMOVE_REGION_LOCATION_CACHE);
+            break;
           }
           TRegionMigrateResult deleteOldRegionPeerResult =
               handler.waitTaskFinish(this.getProcId(), targetDataNode);
           if (deleteOldRegionPeerResult.getTaskStatus() != 
TRegionMaintainTaskStatus.SUCCESS) {
-            throw new ProcedureException("DELETE_OLD_REGION_PEER executed 
failed in DataNode");
+            LOGGER.warn(
+                "DELETE_OLD_REGION_PEER executed failed, procedure will 
continue. You should manually delete region file.");
           }
           setNextState(REMOVE_REGION_LOCATION_CACHE);
           break;
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/testonly/CreateManyDatabasesProcedure.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/testonly/CreateManyDatabasesProcedure.java
index 7d1c0119c23..4693923bb30 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/testonly/CreateManyDatabasesProcedure.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/testonly/CreateManyDatabasesProcedure.java
@@ -32,6 +32,7 @@ import org.slf4j.LoggerFactory;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 
 /**
  * This procedure will create numerous databases (perhaps 100), during which 
the confignode leader
@@ -47,12 +48,13 @@ public class CreateManyDatabasesProcedure
   public static final String DATABASE_NAME_PREFIX = "root.test_";
   public static final long SLEEP_FOREVER = Long.MAX_VALUE;
   private boolean createFailedOnce = false;
+  private boolean isDeserialized = false;
 
   @Override
   protected Flow executeFromState(ConfigNodeProcedureEnv 
configNodeProcedureEnv, Integer state)
       throws InterruptedException {
     if (state < MAX_STATE) {
-      if (state == MAX_STATE - 1 && !isDeserialized()) {
+      if (state == MAX_STATE - 1 && !isDeserialized) {
         Thread.sleep(SLEEP_FOREVER);
       }
       try {
@@ -106,4 +108,10 @@ public class CreateManyDatabasesProcedure
     
stream.writeShort(ProcedureType.CREATE_MANY_DATABASES_PROCEDURE.getTypeCode());
     super.serialize(stream);
   }
+
+  @Override
+  public void deserialize(ByteBuffer byteBuffer) {
+    super.deserialize(byteBuffer);
+    isDeserialized = true;
+  }
 }
diff --git a/iotdb-core/consensus/pom.xml b/iotdb-core/consensus/pom.xml
index b3a160c0dfd..e149e62f6f6 100644
--- a/iotdb-core/consensus/pom.xml
+++ b/iotdb-core/consensus/pom.xml
@@ -128,6 +128,10 @@
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
     </dependencies>
     <build>
         <plugins>
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/IConsensus.java 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/IConsensus.java
index 32dae2c0ff5..27d1340965d 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/IConsensus.java
+++ 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/IConsensus.java
@@ -207,4 +207,23 @@ public interface IConsensus {
    * @return consensusGroupId list
    */
   List<ConsensusGroupId> getAllConsensusGroupIds();
+
+  /**
+   * Return all consensus group ids from disk.
+   *
+   * <p>We need to parse all the RegionGroupIds from the disk directory before 
starting the
+   * consensus layer, and {@link #getAllConsensusGroupIds()} returns an empty 
list, so we need to
+   * add a new interface.
+   *
+   * @return consensusGroupId list
+   */
+  List<ConsensusGroupId> getAllConsensusGroupIdsWithoutStarting();
+
+  /**
+   * Return the region directory of the corresponding consensus group.
+   *
+   * @param groupId the consensus group
+   * @return region directory
+   */
+  String getRegionDirFromConsensusGroupId(ConsensusGroupId groupId);
 }
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
index 385ecaa89fc..a43a5b995a8 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
+++ 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/ConsensusException.java
@@ -28,4 +28,8 @@ public class ConsensusException extends Exception {
   public ConsensusException(String message, Throwable cause) {
     super(message, cause);
   }
+
+  public ConsensusException(Exception e) {
+    super(e);
+  }
 }
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/IoTConsensus.java
 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/IoTConsensus.java
index e9bb1fb6eb5..4da51bd0ad1 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/IoTConsensus.java
+++ 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/IoTConsensus.java
@@ -30,7 +30,8 @@ import org.apache.iotdb.commons.exception.StartupException;
 import org.apache.iotdb.commons.service.RegisterManager;
 import org.apache.iotdb.commons.utils.FileUtils;
 import org.apache.iotdb.commons.utils.KillPoint.DataNodeKillPoints;
-import 
org.apache.iotdb.commons.utils.KillPoint.IoTConsensusRemovePeerKillPoints;
+import 
org.apache.iotdb.commons.utils.KillPoint.IoTConsensusDeleteLocalPeerKillPoints;
+import 
org.apache.iotdb.commons.utils.KillPoint.IoTConsensusRemovePeerCoordinatorKillPoints;
 import org.apache.iotdb.commons.utils.KillPoint.KillPoint;
 import org.apache.iotdb.commons.utils.StatusUtils;
 import org.apache.iotdb.consensus.IConsensus;
@@ -264,6 +265,7 @@ public class IoTConsensus implements IConsensus {
 
   @Override
   public void deleteLocalPeer(ConsensusGroupId groupId) throws 
ConsensusException {
+    
KillPoint.setKillPoint(IoTConsensusDeleteLocalPeerKillPoints.BEFORE_DELETE);
     AtomicBoolean exist = new AtomicBoolean(false);
     stateMachineMap.computeIfPresent(
         groupId,
@@ -273,6 +275,7 @@ public class IoTConsensus implements IConsensus {
           FileUtils.deleteFileOrDirectory(new File(buildPeerDir(storageDir, 
groupId)));
           return null;
         });
+    KillPoint.setKillPoint(IoTConsensusDeleteLocalPeerKillPoints.AFTER_DELETE);
     if (!exist.get()) {
       throw new ConsensusGroupNotExistException(groupId);
     }
@@ -289,7 +292,7 @@ public class IoTConsensus implements IConsensus {
     try {
       // step 1: inactive new Peer to prepare for following steps
       logger.info("[IoTConsensus] inactivate new peer: {}", peer);
-      impl.inactivePeer(peer);
+      impl.inactivePeer(peer, false);
 
       // step 2: take snapshot
       logger.info("[IoTConsensus] start to take snapshot...");
@@ -329,7 +332,7 @@ public class IoTConsensus implements IConsensus {
         logger.error(
             "[IoTConsensus] failed to cleanup side effects after failed to add 
remote peer", mpe);
       }
-      throw new ConsensusException(e.getMessage());
+      throw new ConsensusException(e);
     }
   }
 
@@ -351,7 +354,7 @@ public class IoTConsensus implements IConsensus {
       throw new PeerNotInConsensusGroupException(groupId, peer.toString());
     }
 
-    KillPoint.setKillPoint(IoTConsensusRemovePeerKillPoints.INIT);
+    KillPoint.setKillPoint(IoTConsensusRemovePeerCoordinatorKillPoints.INIT);
 
     try {
       // let other peers remove the sync channel with target peer
@@ -360,18 +363,18 @@ public class IoTConsensus implements IConsensus {
       throw new ConsensusException(e.getMessage());
     }
     KillPoint.setKillPoint(
-        
IoTConsensusRemovePeerKillPoints.AFTER_NOTIFY_PEERS_TO_REMOVE_SYNC_LOG_CHANNEL);
+        
IoTConsensusRemovePeerCoordinatorKillPoints.AFTER_NOTIFY_PEERS_TO_REMOVE_SYNC_LOG_CHANNEL);
 
     try {
       // let target peer reject new write
-      impl.inactivePeer(peer);
-      
KillPoint.setKillPoint(IoTConsensusRemovePeerKillPoints.AFTER_INACTIVE_PEER);
+      impl.inactivePeer(peer, true);
+      
KillPoint.setKillPoint(IoTConsensusRemovePeerCoordinatorKillPoints.AFTER_INACTIVE_PEER);
       // wait its SyncLog to complete
       impl.waitTargetPeerUntilSyncLogCompleted(peer);
     } catch (ConsensusGroupModifyPeerException e) {
       throw new ConsensusException(e.getMessage());
     }
-    KillPoint.setKillPoint(IoTConsensusRemovePeerKillPoints.FINISH);
+    KillPoint.setKillPoint(IoTConsensusRemovePeerCoordinatorKillPoints.FINISH);
   }
 
   @Override
@@ -414,28 +417,74 @@ public class IoTConsensus implements IConsensus {
     return new ArrayList<>(stateMachineMap.keySet());
   }
 
-  public void resetPeerList(ConsensusGroupId groupId, List<Peer> peers) throws 
ConsensusException {
+  @Override
+  public List<ConsensusGroupId> getAllConsensusGroupIdsWithoutStarting() {
+    return getConsensusGroupIdsFromDir(storageDir, logger);
+  }
+
+  public static List<ConsensusGroupId> getConsensusGroupIdsFromDir(File 
storageDir, Logger logger) {
+    List<ConsensusGroupId> consensusGroupIds = new ArrayList<>();
+    try (DirectoryStream<Path> stream = 
Files.newDirectoryStream(storageDir.toPath())) {
+      for (Path path : stream) {
+        try {
+          String[] items = path.getFileName().toString().split("_");
+          ConsensusGroupId consensusGroupId =
+              ConsensusGroupId.Factory.create(
+                  Integer.parseInt(items[0]), Integer.parseInt(items[1]));
+          consensusGroupIds.add(consensusGroupId);
+        } catch (Exception e) {
+          logger.info(
+              "The directory {} is not a group directory;" + " ignoring it. ",
+              path.getFileName().toString());
+        }
+      }
+    } catch (IOException e) {
+      logger.error("Failed to get all consensus group ids from disk", e);
+    }
+    return consensusGroupIds;
+  }
+
+  @Override
+  public String getRegionDirFromConsensusGroupId(ConsensusGroupId groupId) {
+    return buildPeerDir(storageDir, groupId);
+  }
+
+  public void resetPeerList(ConsensusGroupId groupId, List<Peer> correctPeers)
+      throws ConsensusException {
     IoTConsensusServerImpl impl =
         Optional.ofNullable(stateMachineMap.get(groupId))
             .orElseThrow(() -> new ConsensusGroupNotExistException(groupId));
-    if (impl.isReadOnly()) {
-      throw new ConsensusException("system is in read-only status now");
-    } else if (!impl.isActive()) {
-      throw new ConsensusException(
-          "peer is inactive and not ready to receive reset configuration 
request.");
+    Peer localPeer = new Peer(groupId, thisNodeId, thisNode);
+    if (!correctPeers.contains(localPeer)) {
+      logger.warn(
+          "[RESET PEER LIST] Local peer is not in the correct configuration, 
delete local peer {}",
+          groupId);
+      deleteLocalPeer(groupId);
+      return;
     }
-
+    String previousPeerListStr = impl.getConfiguration().toString();
     for (Peer peer : impl.getConfiguration()) {
-      if (!peers.contains(peer)) {
+      if (!correctPeers.contains(peer)) {
         try {
-          removeRemotePeer(groupId, peer);
-        } catch (ConsensusException e) {
-          logger.error("Failed to remove peer {} from group {}", peer, 
groupId, e);
-          throw e;
+          impl.removeSyncLogChannel(peer);
+        } catch (ConsensusGroupModifyPeerException e) {
+          logger.error(
+              "[RESET PEER LIST] Failed to remove peer {}'s sync log channel 
from group {}",
+              peer,
+              groupId,
+              e);
         }
       }
     }
-    impl.resetConfiguration(peers);
+    logger.info(
+        "[RESET PEER LIST] Local peer list has been reset: {} -> {}",
+        previousPeerListStr,
+        impl.getConfiguration());
+    for (Peer peer : correctPeers) {
+      if (!impl.getConfiguration().contains(peer)) {
+        logger.warn("[RESET PEER LIST] \"Correct peer\" {} is not in local 
peer list", peer);
+      }
+    }
   }
 
   public IoTConsensusServerImpl getImpl(ConsensusGroupId groupId) {
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/IoTConsensusServerImpl.java
 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/IoTConsensusServerImpl.java
index cdb797da4e4..9a7153b158b 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/IoTConsensusServerImpl.java
+++ 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/IoTConsensusServerImpl.java
@@ -27,6 +27,8 @@ import 
org.apache.iotdb.commons.consensus.index.ComparableConsensusRequest;
 import org.apache.iotdb.commons.consensus.index.impl.IoTProgressIndex;
 import org.apache.iotdb.commons.service.metric.MetricService;
 import org.apache.iotdb.commons.service.metric.PerformanceOverviewMetrics;
+import org.apache.iotdb.commons.utils.KillPoint.DataNodeKillPoints;
+import org.apache.iotdb.commons.utils.KillPoint.KillPoint;
 import org.apache.iotdb.consensus.IStateMachine;
 import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
@@ -60,6 +62,7 @@ import 
org.apache.iotdb.consensus.iot.thrift.TWaitSyncLogCompleteRes;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.io.FileUtils;
 import org.apache.thrift.TException;
 import org.slf4j.Logger;
@@ -70,10 +73,10 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedList;
@@ -87,6 +90,7 @@ import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 public class IoTConsensusServerImpl {
@@ -134,8 +138,9 @@ public class IoTConsensusServerImpl {
     this.configuration = configuration;
     if (configuration.isEmpty()) {
       recoverConfiguration();
+    } else {
+      persistConfiguration();
     }
-    persistConfiguration();
     this.backgroundTaskService = backgroundTaskService;
     this.config = config;
     this.consensusGroupId = thisNode.getGroupId().toString();
@@ -317,11 +322,10 @@ public class IoTConsensusServerImpl {
       if (!Files.exists(parentDir)) {
         Files.createDirectories(parentDir);
       }
-      Files.write(
-          Paths.get(targetFile.getAbsolutePath()),
-          fileChunk.array(),
-          StandardOpenOption.CREATE,
-          StandardOpenOption.APPEND);
+      try (FileOutputStream fos = new 
FileOutputStream(targetFile.getAbsolutePath(), true);
+          FileChannel channel = fos.getChannel()) {
+        channel.write(fileChunk.slice());
+      }
     } catch (IOException e) {
       throw new ConsensusGroupModifyPeerException(
           String.format("error when receiving snapshot %s", snapshotId), e);
@@ -379,19 +383,30 @@ public class IoTConsensusServerImpl {
     stateMachine.loadSnapshot(new File(storageDir, snapshotId));
   }
 
-  public void inactivePeer(Peer peer) throws ConsensusGroupModifyPeerException 
{
+  @FunctionalInterface
+  public interface ThrowableFunction<T, R> {
+    R apply(T t) throws Exception;
+  }
+
+  public void inactivePeer(Peer peer, boolean forDeletionPurpose)
+      throws ConsensusGroupModifyPeerException {
     try (SyncIoTConsensusServiceClient client =
         syncClientManager.borrowClient(peer.getEndpoint())) {
-      TInactivatePeerRes res =
-          client.inactivatePeer(
-              new 
TInactivatePeerReq(peer.getGroupId().convertToTConsensusGroupId()));
-      if (!isSuccess(res.status)) {
+      try {
+        TInactivatePeerRes res =
+            client.inactivatePeer(
+                new 
TInactivatePeerReq(peer.getGroupId().convertToTConsensusGroupId())
+                    .setForDeletionPurpose(forDeletionPurpose));
+        if (!isSuccess(res.status)) {
+          throw new ConsensusGroupModifyPeerException(
+              String.format("error when inactivating %s. %s", peer, 
res.getStatus()));
+        }
+      } catch (Exception e) {
         throw new ConsensusGroupModifyPeerException(
-            String.format("error when inactivating %s. %s", peer, 
res.getStatus()));
+            String.format("error when inactivating %s", peer), e);
       }
-    } catch (Exception e) {
-      throw new ConsensusGroupModifyPeerException(
-          String.format("error when inactivating %s", peer), e);
+    } catch (ClientManagerException e) {
+      throw new ConsensusGroupModifyPeerException(e);
     }
   }
 
@@ -478,7 +493,7 @@ public class IoTConsensusServerImpl {
       throws ConsensusGroupModifyPeerException {
     // The configuration will be modified during iterating because we will add 
the targetPeer to
     // configuration
-    List<Peer> currentMembers = new ArrayList<>(this.configuration);
+    ImmutableList<Peer> currentMembers = 
ImmutableList.copyOf(this.configuration);
     for (Peer peer : currentMembers) {
       if (peer.equals(targetPeer)) {
         // if the targetPeer is the same as current peer, skip it because 
removing itself is illegal
@@ -562,6 +577,7 @@ public class IoTConsensusServerImpl {
 
   public void buildSyncLogChannel(Peer targetPeer, long initialSyncIndex)
       throws ConsensusGroupModifyPeerException {
+    KillPoint.setKillPoint(DataNodeKillPoints.ORIGINAL_ADD_PEER_DONE);
     // step 1, build sync channel in LogDispatcher
     logger.info(
         "[IoTConsensus] build sync log channel to {} with initialSyncIndex {}",
@@ -591,23 +607,12 @@ public class IoTConsensusServerImpl {
     }
   }
 
-  // TODO: persist first and then delete old configuration file
   public void persistConfiguration() {
     try {
-      try (Stream<Path> stream = Files.walk(Paths.get(storageDir))) {
-        stream
-            .filter(Files::isRegularFile)
-            .filter(filePath -> 
filePath.getFileName().toString().contains("configuration"))
-            .forEach(
-                filePath -> {
-                  try {
-                    Files.delete(filePath);
-                  } catch (IOException e) {
-                    logger.error("Unexpected error occurs when deleting old 
configuration file", e);
-                  }
-                });
-      }
+      renameTmpConfigurationFileToRemoveSuffix();
       serializeConfigurationAndFsyncToDisk();
+      deleteConfiguration();
+      renameTmpConfigurationFileToRemoveSuffix();
     } catch (IOException e) {
       // TODO: (xingtanzjr) need to handle the IOException because the 
IoTConsensus won't
       // work expectedly
@@ -642,6 +647,7 @@ public class IoTConsensusServerImpl {
             configuration.add(peer);
           }
         }
+        persistConfiguration();
       }
       logger.info("Recover IoTConsensus server Impl, configuration: {}", 
configuration);
     } catch (IOException e) {
@@ -657,12 +663,12 @@ public class IoTConsensusServerImpl {
     for (int i = 0; i < size; i++) {
       configuration.add(Peer.deserialize(buffer));
     }
-    // TODO: delete old file before new file persisted is unsafe
+    persistConfiguration();
     Files.delete(oldConfigurationPath);
   }
 
-  public static String generateConfigurationDatFileName(int nodeId) {
-    return nodeId + "_" + CONFIGURATION_FILE_NAME;
+  public static String generateConfigurationDatFileName(int nodeId, String 
suffix) {
+    return nodeId + "_" + suffix;
   }
 
   private List<Peer> getConfiguration(Path dirPath, String 
configurationFileName)
@@ -681,11 +687,6 @@ public class IoTConsensusServerImpl {
     return tmpConfiguration;
   }
 
-  public void resetConfiguration(List<Peer> newConfiguration) {
-    configuration.clear();
-    configuration.addAll(newConfiguration);
-  }
-
   public IndexedConsensusRequest buildIndexedConsensusRequestForLocalRequest(
       IConsensusRequest request) {
     if (request instanceof ComparableConsensusRequest) {
@@ -876,7 +877,8 @@ public class IoTConsensusServerImpl {
 
   private void serializeConfigurationAndFsyncToDisk() throws IOException {
     for (Peer peer : configuration) {
-      String peerConfigurationFileName = 
generateConfigurationDatFileName(peer.getNodeId());
+      String peerConfigurationFileName =
+          generateConfigurationDatFileName(peer.getNodeId(), 
CONFIGURATION_TMP_FILE_NAME);
       FileOutputStream fileOutputStream =
           new FileOutputStream(new File(storageDir, 
peerConfigurationFileName));
       try (DataOutputStream outputStream = new 
DataOutputStream(fileOutputStream)) {
@@ -886,12 +888,58 @@ public class IoTConsensusServerImpl {
           fileOutputStream.flush();
           fileOutputStream.getFD().sync();
         } catch (IOException ignore) {
-          // ignore
+          // ignore sync exception
         }
       }
     }
   }
 
+  private void renameTmpConfigurationFileToRemoveSuffix() throws IOException {
+    try (Stream<Path> stream = Files.walk(Paths.get(storageDir))) {
+      List<Path> paths =
+          stream
+              .filter(Files::isRegularFile)
+              .filter(
+                  filePath ->
+                      
filePath.getFileName().toString().endsWith(CONFIGURATION_TMP_FILE_NAME))
+              .collect(Collectors.toList());
+      for (Path filePath : paths) {
+        String targetPath =
+            filePath.toString().replace(CONFIGURATION_TMP_FILE_NAME, 
CONFIGURATION_FILE_NAME);
+        File targetFile = new File(targetPath);
+        if (targetFile.exists()) {
+          try {
+            Files.delete(targetFile.toPath());
+          } catch (IOException e) {
+            logger.error("Unexpected error occurs when delete file: {}", 
targetPath);
+          }
+        }
+        if (!filePath.toFile().renameTo(targetFile)) {
+          logger.error("Unexpected error occurs when rename file: {} -> {}", 
filePath, targetPath);
+        }
+      }
+    }
+  }
+
+  private void deleteConfiguration() throws IOException {
+    try (Stream<Path> stream = Files.walk(Paths.get(storageDir))) {
+      stream
+          .filter(Files::isRegularFile)
+          .filter(filePath -> 
filePath.getFileName().toString().endsWith(CONFIGURATION_FILE_NAME))
+          .forEach(
+              filePath -> {
+                try {
+                  Files.delete(filePath);
+                } catch (IOException e) {
+                  logger.error(
+                      "Unexpected error occurs when deleting old configuration 
file {}",
+                      filePath,
+                      e);
+                }
+              });
+    }
+  }
+
   /**
    * This method is used for write of IoTConsensus SyncLog. By this method, we 
can keep write order
    * in follower the same as the leader. And besides order insurance, we can 
make the
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/service/IoTConsensusRPCServiceProcessor.java
 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/service/IoTConsensusRPCServiceProcessor.java
index 6c4b7cc6777..1c5f5354c82 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/service/IoTConsensusRPCServiceProcessor.java
+++ 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/iot/service/IoTConsensusRPCServiceProcessor.java
@@ -22,6 +22,7 @@ package org.apache.iotdb.consensus.iot.service;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import org.apache.iotdb.commons.utils.KillPoint.DataNodeKillPoints;
+import 
org.apache.iotdb.commons.utils.KillPoint.IoTConsensusInactivatePeerKillPoints;
 import org.apache.iotdb.commons.utils.KillPoint.KillPoint;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.common.request.BatchIndexedConsensusRequest;
@@ -139,6 +140,9 @@ public class IoTConsensusRPCServiceProcessor implements 
IoTConsensusIService.Asy
   public void inactivatePeer(
       TInactivatePeerReq req, AsyncMethodCallback<TInactivatePeerRes> 
resultHandler)
       throws TException {
+    if (req.isForDeletionPurpose()) {
+      
KillPoint.setKillPoint(IoTConsensusInactivatePeerKillPoints.BEFORE_INACTIVATE);
+    }
     ConsensusGroupId groupId =
         
ConsensusGroupId.Factory.createFromTConsensusGroupId(req.getConsensusGroupId());
     IoTConsensusServerImpl impl = consensus.getImpl(groupId);
@@ -154,6 +158,9 @@ public class IoTConsensusRPCServiceProcessor implements 
IoTConsensusIService.Asy
     impl.setActive(false);
     resultHandler.onComplete(
         new TInactivatePeerRes(new 
TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode())));
+    if (req.isForDeletionPurpose()) {
+      
KillPoint.setKillPoint(IoTConsensusInactivatePeerKillPoints.AFTER_INACTIVATE);
+    }
   }
 
   @Override
@@ -201,7 +208,6 @@ public class IoTConsensusRPCServiceProcessor implements 
IoTConsensusIService.Asy
       responseStatus = new 
TSStatus(TSStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
       responseStatus.setMessage(e.getMessage());
     }
-    KillPoint.setKillPoint(DataNodeKillPoints.ORIGINAL_ADD_PEER_DONE);
     resultHandler.onComplete(new TBuildSyncLogChannelRes(responseStatus));
   }
 
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/ratis/RatisConsensus.java
 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/ratis/RatisConsensus.java
index 3a6082ae2fe..d06c7c93fe2 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/ratis/RatisConsensus.java
+++ 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/ratis/RatisConsensus.java
@@ -90,11 +90,15 @@ import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -110,6 +114,8 @@ class RatisConsensus implements IConsensus {
   /** The unique net communication endpoint */
   private final RaftPeer myself;
 
+  private final File storageDir;
+
   private final RaftServer server;
 
   private final RaftProperties properties = new RaftProperties();
@@ -143,9 +149,9 @@ class RatisConsensus implements IConsensus {
     myself =
         Utils.fromNodeInfoAndPriorityToRaftPeer(
             config.getThisNodeId(), config.getThisNodeEndPoint(), 
DEFAULT_PRIORITY);
+    this.storageDir = new File(config.getStorageDir());
 
-    RaftServerConfigKeys.setStorageDir(
-        properties, Collections.singletonList(new 
File(config.getStorageDir())));
+    RaftServerConfigKeys.setStorageDir(properties, 
Collections.singletonList(storageDir));
     GrpcConfigKeys.Server.setPort(properties, 
config.getThisNodeEndPoint().getPort());
 
     Utils.initRatisConfig(properties, config.getRatisConfig());
@@ -688,6 +694,33 @@ class RatisConsensus implements IConsensus {
     return ids;
   }
 
+  @Override
+  public List<ConsensusGroupId> getAllConsensusGroupIdsWithoutStarting() {
+    List<ConsensusGroupId> consensusGroupIds = new ArrayList<>();
+    try (DirectoryStream<Path> stream = 
Files.newDirectoryStream(storageDir.toPath())) {
+      for (Path path : stream) {
+        try {
+          RaftGroupId raftGroupId =
+              
RaftGroupId.valueOf(UUID.fromString(path.getFileName().toString()));
+          
consensusGroupIds.add(Utils.fromRaftGroupIdToConsensusGroupId(raftGroupId));
+        } catch (Exception e) {
+          logger.info(
+              "The directory {} is not a group directory;" + " ignoring it. ",
+              path.getFileName().toString());
+        }
+      }
+    } catch (IOException e) {
+      logger.error("Failed to get all consensus group ids from disk", e);
+    }
+    return consensusGroupIds;
+  }
+
+  @Override
+  public String getRegionDirFromConsensusGroupId(ConsensusGroupId 
consensusGroupId) {
+    RaftGroupId raftGroupId = 
Utils.fromConsensusGroupIdToRaftGroupId(consensusGroupId);
+    return storageDir + File.separator + raftGroupId.getUuid().toString();
+  }
+
   @Override
   public void triggerSnapshot(ConsensusGroupId groupId, boolean force) throws 
ConsensusException {
     final RaftGroupId raftGroupId = 
Utils.fromConsensusGroupIdToRaftGroupId(groupId);
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleConsensus.java
 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleConsensus.java
index d23086b51a7..3f35944ced7 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleConsensus.java
+++ 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleConsensus.java
@@ -38,6 +38,7 @@ import 
org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupNotExistException;
 import org.apache.iotdb.consensus.exception.IllegalPeerEndpointException;
 import org.apache.iotdb.consensus.exception.IllegalPeerNumException;
+import org.apache.iotdb.consensus.iot.IoTConsensus;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.slf4j.Logger;
@@ -243,6 +244,16 @@ class SimpleConsensus implements IConsensus {
     return new ArrayList<>(stateMachineMap.keySet());
   }
 
+  @Override
+  public List<ConsensusGroupId> getAllConsensusGroupIdsWithoutStarting() {
+    return IoTConsensus.getConsensusGroupIdsFromDir(storageDir, logger);
+  }
+
+  @Override
+  public String getRegionDirFromConsensusGroupId(ConsensusGroupId groupId) {
+    return buildPeerDir(groupId);
+  }
+
   @Override
   public void resetPeerList(ConsensusGroupId groupId, List<Peer> peers) throws 
ConsensusException {
     throw new ConsensusException("SimpleConsensus does not support reset peer 
list");
diff --git 
a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/iot/ReplicateTest.java
 
b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/iot/ReplicateTest.java
index 0e7eb9e1559..6a636542df3 100644
--- 
a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/iot/ReplicateTest.java
+++ 
b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/iot/ReplicateTest.java
@@ -307,6 +307,27 @@ public class ReplicateTest {
     }
   }
 
+  @Test
+  public void parsingAndConstructIDTest() throws Exception {
+    logger.info("Start ParsingAndConstructIDTest");
+    servers.get(0).createLocalPeer(group.getGroupId(), group.getPeers());
+    for (int i = 0; i < CHECK_POINT_GAP; i++) {
+      servers.get(0).write(gid, new TestEntry(i, peers.get(0)));
+    }
+    List<ConsensusGroupId> ids = 
servers.get(0).getAllConsensusGroupIdsWithoutStarting();
+
+    Assert.assertEquals(1, ids.size());
+    Assert.assertEquals(gid, ids.get(0));
+
+    String regionDir = servers.get(0).getRegionDirFromConsensusGroupId(gid);
+    try {
+      File regionDirFile = new File(regionDir);
+      Assert.assertTrue(regionDirFile.exists());
+    } catch (Exception e) {
+      Assert.fail();
+    }
+  }
+
   private void findPortAvailable(int i) {
     long start = System.currentTimeMillis();
     while (System.currentTimeMillis() - start < timeout) {
diff --git 
a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/iot/StabilityTest.java
 
b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/iot/StabilityTest.java
index f94c489a2f7..7e176242dc7 100644
--- 
a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/iot/StabilityTest.java
+++ 
b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/iot/StabilityTest.java
@@ -102,7 +102,7 @@ public class StabilityTest {
     try {
       consensusImpl.createLocalPeer(
           dataRegionId,
-          Collections.singletonList(new Peer(dataRegionId, 1, new 
TEndPoint("0.0.0.0", 6667))));
+          Collections.singletonList(new Peer(dataRegionId, 1, new 
TEndPoint("0.0.0.0", basePort))));
     } catch (ConsensusException e) {
       Assert.fail();
     }
@@ -110,7 +110,7 @@ public class StabilityTest {
     try {
       consensusImpl.createLocalPeer(
           dataRegionId,
-          Collections.singletonList(new Peer(dataRegionId, 1, new 
TEndPoint("0.0.0.0", 6667))));
+          Collections.singletonList(new Peer(dataRegionId, 1, new 
TEndPoint("0.0.0.0", basePort))));
       Assert.fail();
     } catch (ConsensusException e) {
       assertTrue(e instanceof ConsensusGroupAlreadyExistException);
@@ -126,7 +126,7 @@ public class StabilityTest {
     try {
       consensusImpl.createLocalPeer(
           dataRegionId,
-          Collections.singletonList(new Peer(dataRegionId, 1, new 
TEndPoint("0.0.0.1", 6667))));
+          Collections.singletonList(new Peer(dataRegionId, 1, new 
TEndPoint("0.0.0.1", basePort))));
       Assert.fail();
     } catch (ConsensusException e) {
       assertTrue(e instanceof IllegalPeerEndpointException);
@@ -150,7 +150,7 @@ public class StabilityTest {
     try {
       consensusImpl.createLocalPeer(
           dataRegionId,
-          Collections.singletonList(new Peer(dataRegionId, 1, new 
TEndPoint("0.0.0.0", 6667))));
+          Collections.singletonList(new Peer(dataRegionId, 1, new 
TEndPoint("0.0.0.0", basePort))));
       consensusImpl.deleteLocalPeer(dataRegionId);
     } catch (ConsensusException e) {
       Assert.fail();
@@ -177,8 +177,8 @@ public class StabilityTest {
   public void transferLeader() {
     try {
       consensusImpl.transferLeader(
-          dataRegionId, new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 
6667)));
-      Assert.fail("Can't transfer leader in SimpleConsensus.");
+          dataRegionId, new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 
basePort)));
+      Assert.fail("Can't transfer leader in IoTConsensus.");
     } catch (ConsensusException e) {
       // not handle
     }
diff --git 
a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/RatisConsensusTest.java
 
b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/RatisConsensusTest.java
index 7dcf98caceb..d164cac4316 100644
--- 
a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/RatisConsensusTest.java
+++ 
b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/RatisConsensusTest.java
@@ -38,6 +38,7 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
@@ -274,6 +275,24 @@ public class RatisConsensusTest {
     doConsensus(1, 10, 20);
   }
 
+  @Test
+  public void parsingAndConstructIDs() throws Exception {
+    servers.get(0).createLocalPeer(gid, peers.subList(0, 1));
+    doConsensus(0, 10, 10);
+
+    List<ConsensusGroupId> ids = 
servers.get(0).getAllConsensusGroupIdsWithoutStarting();
+    Assert.assertEquals(1, ids.size());
+    Assert.assertEquals(gid, ids.get(0));
+
+    String regionDir = servers.get(0).getRegionDirFromConsensusGroupId(gid);
+    try {
+      File regionDirFile = new File(regionDir);
+      Assert.assertTrue(regionDirFile.exists());
+    } catch (Exception e) {
+      Assert.fail();
+    }
+  }
+
   private void doConsensus(int serverIndex, int count, int target) throws 
Exception {
     miniCluster.writeManyParallel(writeExecutor, serverIndex, count);
     Assert.assertEquals(target, miniCluster.mustRead(serverIndex));
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
index 38a973d554d..ae288312599 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
@@ -287,15 +287,16 @@ public class DataRegionStateMachine extends 
BaseStateMachine {
 
   @Override
   public File getSnapshotRoot() {
-    String snapshotDir =
-        
IoTDBDescriptor.getInstance().getConfig().getRatisDataRegionSnapshotDir()
-            + File.separator
-            + region.getDatabaseName()
-            + "-"
-            + region.getDataRegionId();
+    String snapshotDir = "";
     try {
+      snapshotDir =
+          
IoTDBDescriptor.getInstance().getConfig().getRatisDataRegionSnapshotDir()
+              + File.separator
+              + region.getDatabaseName()
+              + "-"
+              + region.getDataRegionId();
       return new File(snapshotDir).getCanonicalFile();
-    } catch (IOException e) {
+    } catch (IOException | NullPointerException e) {
       logger.warn("{}: cannot get the canonical file of {} due to {}", this, 
snapshotDir, e);
       return null;
     }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
index 1cdd3406574..e9752f828c7 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
@@ -57,7 +57,6 @@ import 
org.apache.iotdb.confignode.rpc.thrift.TNodeVersionInfo;
 import org.apache.iotdb.confignode.rpc.thrift.TRuntimeConfiguration;
 import org.apache.iotdb.confignode.rpc.thrift.TSystemConfigurationResp;
 import org.apache.iotdb.consensus.ConsensusFactory;
-import org.apache.iotdb.consensus.iot.IoTConsensus;
 import org.apache.iotdb.db.conf.DataNodeStartupCheck;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
@@ -112,9 +111,6 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -457,55 +453,30 @@ public class DataNode implements DataNodeMBean {
     }
   }
 
-  // TODO: Implement in IConsensus, not in DataNode
-  private List<ConsensusGroupId> getConsensusGroupId() {
-    List<ConsensusGroupId> consensusGroupIds = new ArrayList<>();
-    String dataRegionConsensusDir = config.getDataRegionConsensusDir();
-    if 
(config.getDataRegionConsensusProtocolClass().equals(ConsensusFactory.RATIS_CONSENSUS))
 {
-      return consensusGroupIds;
-    }
-    try (DirectoryStream<Path> stream =
-        Files.newDirectoryStream(new File(dataRegionConsensusDir).toPath())) {
-      for (Path path : stream) {
-        String[] items = path.getFileName().toString().split("_");
-        ConsensusGroupId consensusGroupId =
-            ConsensusGroupId.Factory.create(Integer.parseInt(items[0]), 
Integer.parseInt(items[1]));
-        consensusGroupIds.add(consensusGroupId);
-      }
-    } catch (IOException e) {
-      logger.error("Cannot get consensus group id from {}", 
dataRegionConsensusDir, e);
-    }
-    return consensusGroupIds;
-  }
-
-  // TODO: remove for current version, add todo for rename
-  private void renameInvalidRegionDirs(List<ConsensusGroupId> 
invalidConsensusGroupIds) {
-    for (ConsensusGroupId consensusGroupId : invalidConsensusGroupIds) {
-      File oldDir =
-          new File(
-              IoTConsensus.buildPeerDir(
-                  new File(config.getDataRegionConsensusDir()), 
consensusGroupId));
-      File newDir =
-          new File(
-              IoTConsensus.buildPeerDir(
-                  new File(config.getInvalidDataRegionConsensusDir()), 
consensusGroupId));
-      if (oldDir.exists() && !FileUtils.moveFileSafe(oldDir, newDir)) {
-        logger.error("move {} to {} failed.", oldDir.getAbsolutePath(), 
newDir.getAbsolutePath());
-        try {
-          FileUtils.recursivelyDeleteFolder(oldDir.getPath());
-        } catch (IOException e) {
-          logger.error("delete {} failed.", oldDir.getAbsolutePath());
-        }
-      }
-    }
-  }
-
   private void removeInvalidRegions(List<ConsensusGroupId> 
dataNodeConsensusGroupIds) {
     List<ConsensusGroupId> invalidConsensusGroupIds =
-        getConsensusGroupId().stream()
+        
DataRegionConsensusImpl.getInstance().getAllConsensusGroupIdsWithoutStarting().stream()
             .filter(consensusGroupId -> 
!dataNodeConsensusGroupIds.contains(consensusGroupId))
             .collect(Collectors.toList());
-    renameInvalidRegionDirs(invalidConsensusGroupIds);
+    if (!invalidConsensusGroupIds.isEmpty()) {
+      logger.info("Remove invalid region directories... {}", 
invalidConsensusGroupIds);
+      for (ConsensusGroupId consensusGroupId : invalidConsensusGroupIds) {
+        File oldDir =
+            new File(
+                DataRegionConsensusImpl.getInstance()
+                    .getRegionDirFromConsensusGroupId(consensusGroupId));
+        if (oldDir.exists()) {
+          try {
+            FileUtils.recursivelyDeleteFolder(oldDir.getPath());
+            logger.info("delete {} succeed.", oldDir.getAbsolutePath());
+          } catch (IOException e) {
+            logger.error("delete {} failed.", oldDir.getAbsolutePath());
+          }
+        } else {
+          logger.info("delete {} failed, because it does not exist.", 
oldDir.getAbsolutePath());
+        }
+      }
+    }
   }
 
   private void sendRestartRequestToConfigNode() throws StartupException {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RegionMigrateService.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RegionMigrateService.java
index df07d3d7487..c021920f27a 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RegionMigrateService.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RegionMigrateService.java
@@ -38,8 +38,7 @@ import 
org.apache.iotdb.consensus.exception.PeerAlreadyInConsensusGroupException
 import org.apache.iotdb.consensus.exception.PeerNotInConsensusGroupException;
 import org.apache.iotdb.db.consensus.DataRegionConsensusImpl;
 import org.apache.iotdb.db.consensus.SchemaRegionConsensusImpl;
-import org.apache.iotdb.db.schemaengine.SchemaEngine;
-import org.apache.iotdb.db.storageengine.StorageEngine;
+import org.apache.iotdb.db.protocol.thrift.impl.DataNodeRegionManager;
 import org.apache.iotdb.db.storageengine.rescon.memory.AbstractPoolManager;
 import org.apache.iotdb.mpp.rpc.thrift.TMaintainPeerReq;
 import org.apache.iotdb.mpp.rpc.thrift.TRegionMigrateResult;
@@ -524,9 +523,9 @@ public class RegionMigrateService implements IService {
       ConsensusGroupId regionId = 
ConsensusGroupId.Factory.createFromTConsensusGroupId(tRegionId);
       try {
         if (regionId instanceof DataRegionId) {
-          StorageEngine.getInstance().deleteDataRegion((DataRegionId) 
regionId);
+          DataNodeRegionManager.getInstance().deleteDataRegion((DataRegionId) 
regionId);
         } else {
-          SchemaEngine.getInstance().deleteSchemaRegion((SchemaRegionId) 
regionId);
+          
DataNodeRegionManager.getInstance().deleteSchemaRegion((SchemaRegionId) 
regionId);
         }
       } catch (Exception e) {
         taskLogger.error("{}, deleteRegion {} error", REGION_MIGRATE_PROCESS, 
regionId, e);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/SnapshotLoader.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/SnapshotLoader.java
index 5e04f1f2f35..795bd960d7c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/SnapshotLoader.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/snapshot/SnapshotLoader.java
@@ -124,12 +124,6 @@ public class SnapshotLoader {
         return null;
       }
       LOGGER.info("Moving snapshot file to data dirs");
-      try {
-        deleteAllFilesInDataDirs();
-        LOGGER.info("Remove all data files in original data dir");
-      } catch (IOException e) {
-        return null;
-      }
       createLinksFromSnapshotDirToDataDirWithoutLog(new File(snapshotPath));
       return loadSnapshot();
     } catch (IOException | DiskSpaceInsufficientException e) {
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusDeleteLocalPeerKillPoints.java
similarity index 86%
copy from 
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
copy to 
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusDeleteLocalPeerKillPoints.java
index 4f80aa87212..ea8352c7634 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusDeleteLocalPeerKillPoints.java
@@ -19,9 +19,7 @@
 
 package org.apache.iotdb.commons.utils.KillPoint;
 
-public enum IoTConsensusRemovePeerKillPoints {
-  INIT,
-  AFTER_NOTIFY_PEERS_TO_REMOVE_SYNC_LOG_CHANNEL,
-  AFTER_INACTIVE_PEER,
-  FINISH,
+public enum IoTConsensusDeleteLocalPeerKillPoints {
+  BEFORE_DELETE,
+  AFTER_DELETE,
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusInactivatePeerKillPoints.java
similarity index 86%
copy from 
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
copy to 
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusInactivatePeerKillPoints.java
index 4f80aa87212..f21577db8ea 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusInactivatePeerKillPoints.java
@@ -19,9 +19,7 @@
 
 package org.apache.iotdb.commons.utils.KillPoint;
 
-public enum IoTConsensusRemovePeerKillPoints {
-  INIT,
-  AFTER_NOTIFY_PEERS_TO_REMOVE_SYNC_LOG_CHANNEL,
-  AFTER_INACTIVE_PEER,
-  FINISH,
+public enum IoTConsensusInactivatePeerKillPoints {
+  BEFORE_INACTIVATE,
+  AFTER_INACTIVATE,
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerCoordinatorKillPoints.java
similarity index 94%
copy from 
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
copy to 
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerCoordinatorKillPoints.java
index 4f80aa87212..14a2ce9f439 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerCoordinatorKillPoints.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.commons.utils.KillPoint;
 
-public enum IoTConsensusRemovePeerKillPoints {
+public enum IoTConsensusRemovePeerCoordinatorKillPoints {
   INIT,
   AFTER_NOTIFY_PEERS_TO_REMOVE_SYNC_LOG_CHANNEL,
   AFTER_INACTIVE_PEER,
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/KillNode.java
similarity index 86%
rename from 
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
rename to 
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/KillNode.java
index 4f80aa87212..1ecba5f303b 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/IoTConsensusRemovePeerKillPoints.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/KillPoint/KillNode.java
@@ -19,9 +19,10 @@
 
 package org.apache.iotdb.commons.utils.KillPoint;
 
-public enum IoTConsensusRemovePeerKillPoints {
-  INIT,
-  AFTER_NOTIFY_PEERS_TO_REMOVE_SYNC_LOG_CHANNEL,
-  AFTER_INACTIVE_PEER,
-  FINISH,
+public enum KillNode {
+  ALL_NODES,
+  CONFIG_NODE,
+  ORIGINAL_DATANODE,
+  DESTINATION_DATANODE,
+  COORDINATOR_DATANODE,
 }
diff --git 
a/iotdb-protocol/thrift-consensus/src/main/thrift/iotconsensus.thrift 
b/iotdb-protocol/thrift-consensus/src/main/thrift/iotconsensus.thrift
index 5810ff97a96..c1957eaf114 100644
--- a/iotdb-protocol/thrift-consensus/src/main/thrift/iotconsensus.thrift
+++ b/iotdb-protocol/thrift-consensus/src/main/thrift/iotconsensus.thrift
@@ -41,6 +41,7 @@ struct TSyncLogEntriesRes {
 
 struct TInactivatePeerReq {
   1: required common.TConsensusGroupId consensusGroupId
+  2: optional bool forDeletionPurpose
 }
 
 struct TInactivatePeerRes {


Reply via email to