You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ta...@apache.org on 2023/08/23 02:29:41 UTC

[iotdb] 01/01: [IOTDB-6121] Consensus layer interface and exception handling refactoring (#10896)

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

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

commit 5d5792216bb94124fef8443a0d4d970d3078e0ce
Author: Potato <ta...@apache.org>
AuthorDate: Wed Aug 23 10:10:58 2023 +0800

    [IOTDB-6121] Consensus layer interface and exception handling refactoring (#10896)
---
 .../confignode/manager/ClusterQuotaManager.java    |  52 ++--
 .../iotdb/confignode/manager/ConfigManager.java    |  18 +-
 .../iotdb/confignode/manager/ModelManager.java     |  75 +++---
 .../confignode/manager/PermissionManager.java      |  39 ++-
 .../iotdb/confignode/manager/TriggerManager.java   |  56 ++--
 .../iotdb/confignode/manager/UDFManager.java       |  28 +-
 .../manager/consensus/ConsensusManager.java        |  84 +++---
 .../iotdb/confignode/manager/cq/CQManager.java     |  42 ++-
 .../confignode/manager/cq/CQScheduleTask.java      |  26 +-
 .../iotdb/confignode/manager/node/NodeManager.java |  73 +++--
 .../manager/partition/PartitionManager.java        | 187 +++++++++----
 .../manager/pipe/plugin/PipePluginCoordinator.java |  23 +-
 .../manager/pipe/task/PipeTaskCoordinator.java     |  14 +-
 .../manager/schema/ClusterSchemaManager.java       | 276 ++++++++++++++++---
 .../procedure/env/ConfigNodeProcedureEnv.java      |  18 +-
 .../procedure/env/DataNodeRemoveHandler.java       |   7 +-
 .../procedure/impl/cq/CreateCQProcedure.java       | 113 ++++----
 .../procedure/impl/model/CreateModelProcedure.java |  18 +-
 .../procedure/impl/model/DropModelProcedure.java   |   7 +-
 .../pipe/plugin/CreatePipePluginProcedure.java     |  27 +-
 .../impl/pipe/plugin/DropPipePluginProcedure.java  |  13 +-
 .../runtime/PipeHandleLeaderChangeProcedure.java   |  19 +-
 .../runtime/PipeHandleMetaChangeProcedure.java     |  23 +-
 .../impl/pipe/task/CreatePipeProcedureV2.java      |  42 ++-
 .../impl/pipe/task/DropPipeProcedureV2.java        |  18 +-
 .../impl/pipe/task/StartPipeProcedureV2.java       |  42 ++-
 .../impl/pipe/task/StopPipeProcedureV2.java        |  42 ++-
 .../impl/schema/DeleteDatabaseProcedure.java       |   3 +-
 .../impl/schema/SetTemplateProcedure.java          |  77 ++++--
 .../statemachine/CreateRegionGroupsProcedure.java  |   7 +-
 .../impl/trigger/CreateTriggerProcedure.java       |  22 +-
 .../procedure/store/ConfigProcedureStore.java      |  13 +-
 .../thrift/ConfigNodeRPCServiceProcessor.java      |   8 +-
 iotdb-core/consensus/pom.xml                       |   2 +-
 .../org/apache/iotdb/consensus/IConsensus.java     | 166 +++++++-----
 .../iotdb/consensus/common/ConsensusGroup.java     |   1 -
 .../org/apache/iotdb/consensus/common/Peer.java    |   1 -
 .../org/apache/iotdb/consensus/common/Utils.java   |  13 +-
 .../common/request/ByteBufferConsensusRequest.java |  12 +-
 .../common/response/ConsensusGenericResponse.java  |  64 -----
 .../common/response/ConsensusReadResponse.java     |  69 -----
 .../common/response/ConsensusResponse.java         |  39 ---
 .../common/response/ConsensusWriteResponse.java    |  82 ------
 .../iotdb/consensus/config/ConsensusConfig.java    |  18 +-
 .../consensus/exception/NodeReadOnlyException.java |  31 ---
 .../PeerNotInConsensusGroupException.java          |   6 +-
 .../exception/RatisUnderRecoveryException.java     |   3 +-
 .../apache/iotdb/consensus/iot/IoTConsensus.java   | 222 +++++++--------
 .../iotdb/consensus/ratis/RatisConsensus.java      | 248 +++++++----------
 .../iotdb/consensus/simple/SimpleConsensus.java    | 142 +++++-----
 ...verImpl.java => SimpleConsensusServerImpl.java} |   4 +-
 .../apache/iotdb/consensus/iot/ReplicateTest.java  |  18 +-
 .../apache/iotdb/consensus/iot/StabilityTest.java  | 106 ++++++--
 .../iotdb/consensus/ratis/RatisConsensusTest.java  | 130 +++++----
 .../iotdb/consensus/ratis/RecoverReadTest.java     |  49 ++--
 .../apache/iotdb/consensus/ratis/TestUtils.java    |  18 +-
 .../iotdb/consensus/simple/RecoveryTest.java       |  22 +-
 .../consensus/simple/SimpleConsensusTest.java      | 228 ++++++++--------
 .../db/consensus/DataRegionConsensusImpl.java      | 299 ++++++++++-----------
 .../db/consensus/SchemaRegionConsensusImpl.java    | 216 ++++++++-------
 .../iotdb/db/protocol/client/ConfigNodeClient.java |   2 +-
 .../impl/DataNodeInternalRPCServiceImpl.java       | 124 +++++----
 .../thrift/impl/DataNodeRegionManager.java         |  47 ++--
 .../execution/executor/RegionReadExecutor.java     |  18 +-
 .../execution/executor/RegionWriteExecutor.java    | 104 +++----
 .../template/ClusterTemplateManager.java           |   3 +-
 .../java/org/apache/iotdb/db/service/DataNode.java |  12 +-
 .../apache/iotdb/db/service/IoTDBShutdownHook.java |  25 +-
 .../iotdb/db/service/RegionMigrateService.java     | 101 +++----
 .../execution/executor/RegionReadExecutorTest.java |  31 +--
 .../executor/RegionWriteExecutorTest.java          |  24 +-
 .../DataNodeInternalRPCServiceImplTest.java        |   8 +-
 .../iotdb/commons/consensus/ConsensusGroupId.java  |  38 ++-
 .../apache/iotdb/commons/utils/StatusUtils.java    |   2 +-
 .../pom.xml                                        |   6 +-
 .../src/main/thrift/iotconsensus.thrift            |   0
 pom.xml                                            |   4 +-
 77 files changed, 2247 insertions(+), 2023 deletions(-)

diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterQuotaManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterQuotaManager.java
index e013d1f6d46..0c00005fc1b 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterQuotaManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ClusterQuotaManager.java
@@ -36,7 +36,7 @@ import org.apache.iotdb.confignode.persistence.quota.QuotaInfo;
 import org.apache.iotdb.confignode.rpc.thrift.TShowThrottleReq;
 import org.apache.iotdb.confignode.rpc.thrift.TSpaceQuotaResp;
 import org.apache.iotdb.confignode.rpc.thrift.TThrottleQuotaResp;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 
@@ -79,12 +79,12 @@ public class ClusterQuotaManager {
           "The used quota exceeds the preset quota. Please set a larger value.");
     }
     // TODO: Datanode failed to receive rpc
-    ConsensusWriteResponse response =
-        configManager
-            .getConsensusManager()
-            .write(new SetSpaceQuotaPlan(req.getDatabase(), req.getSpaceLimit()));
-    if (response.getStatus() != null) {
-      if (response.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+    try {
+      TSStatus response =
+          configManager
+              .getConsensusManager()
+              .write(new SetSpaceQuotaPlan(req.getDatabase(), req.getSpaceLimit()));
+      if (response.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         Map<Integer, TDataNodeLocation> dataNodeLocationMap =
             configManager.getNodeManager().getRegisteredDataNodeLocations();
         AsyncClientHandler<TSetSpaceQuotaReq, TSStatus> clientHandler =
@@ -92,15 +92,16 @@ public class ClusterQuotaManager {
         AsyncDataNodeClientPool.getInstance().sendAsyncRequestToDataNodeWithRetry(clientHandler);
         return RpcUtils.squashResponseStatusList(clientHandler.getResponseList());
       }
-      return response.getStatus();
-    } else {
+      return response;
+    } catch (ConsensusException e) {
       LOGGER.warn(
-          "Unexpected error happened while setting space quota on {}: ",
-          req.getDatabase().toString(),
-          response.getException());
+          String.format(
+              "Unexpected error happened while setting space quota on database: %s ",
+              req.getDatabase()),
+          e);
       // consensus layer related errors
       TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
-      res.setMessage(response.getErrorMessage());
+      res.setMessage(e.getMessage());
       return res;
     }
   }
@@ -183,12 +184,12 @@ public class ClusterQuotaManager {
   }
 
   public TSStatus setThrottleQuota(TSetThrottleQuotaReq req) {
-    ConsensusWriteResponse response =
-        configManager
-            .getConsensusManager()
-            .write(new SetThrottleQuotaPlan(req.getUserName(), req.getThrottleQuota()));
-    if (response.getStatus() != null) {
-      if (response.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+    try {
+      TSStatus response =
+          configManager
+              .getConsensusManager()
+              .write(new SetThrottleQuotaPlan(req.getUserName(), req.getThrottleQuota()));
+      if (response.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         Map<Integer, TDataNodeLocation> dataNodeLocationMap =
             configManager.getNodeManager().getRegisteredDataNodeLocations();
         AsyncClientHandler<TSetThrottleQuotaReq, TSStatus> clientHandler =
@@ -197,15 +198,16 @@ public class ClusterQuotaManager {
         AsyncDataNodeClientPool.getInstance().sendAsyncRequestToDataNodeWithRetry(clientHandler);
         return RpcUtils.squashResponseStatusList(clientHandler.getResponseList());
       }
-      return response.getStatus();
-    } else {
+      return response;
+    } catch (ConsensusException e) {
       LOGGER.warn(
-          "Unexpected error happened while setting throttle quota on user: {}: ",
-          req.getUserName(),
-          response.getException());
+          String.format(
+              "Unexpected error happened while setting throttle quota on user: %s ",
+              req.getUserName()),
+          e);
       // consensus layer related errors
       TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
-      res.setMessage(response.getErrorMessage());
+      res.setMessage(e.getMessage());
       return res;
     }
   }
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
index f1f6cbdef2f..e6c5500d007 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
@@ -172,6 +172,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TUnsetSchemaTemplateReq;
 import org.apache.iotdb.confignode.rpc.thrift.TUpdateModelInfoReq;
 import org.apache.iotdb.confignode.rpc.thrift.TUpdateModelStateReq;
 import org.apache.iotdb.consensus.common.DataSet;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.schemaengine.template.Template;
 import org.apache.iotdb.db.schemaengine.template.TemplateAlterOperationType;
 import org.apache.iotdb.db.schemaengine.template.alter.TemplateAlterOperationUtil;
@@ -360,11 +361,7 @@ public class ConfigManager implements IManager {
   @Override
   public TDataNodeRestartResp restartDataNode(TDataNodeRestartReq req) {
     TSStatus status = confirmLeader();
-    // Notice: The Seed-ConfigNode must also have the privilege to do Node restart check.
-    // Otherwise, the IoTDB-cluster will not have the ability to restart from scratch.
-    if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()
-        || ConfigNodeDescriptor.getInstance().isSeedConfigNode()
-        || SystemPropertiesUtils.isSeedConfigNode()) {
+    if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       status =
           ClusterNodeStartUtils.confirmNodeRestart(
               NodeType.DataNode,
@@ -376,7 +373,6 @@ public class ConfigManager implements IManager {
         return nodeManager.updateDataNodeIfNecessary(req);
       }
     }
-
     return new TDataNodeRestartResp()
         .setStatus(status)
         .setConfigNodeList(getNodeManager().getRegisteredConfigNodes());
@@ -664,8 +660,7 @@ public class ConfigManager implements IManager {
         new GetSchemaPartitionPlan(
             partitionSlotsMap.entrySet().stream()
                 .collect(Collectors.toMap(Map.Entry::getKey, e -> new ArrayList<>(e.getValue()))));
-    SchemaPartitionResp queryResult =
-        (SchemaPartitionResp) partitionManager.getSchemaPartition(getSchemaPartitionPlan);
+    SchemaPartitionResp queryResult = partitionManager.getSchemaPartition(getSchemaPartitionPlan);
     resp = queryResult.convertToRpcSchemaPartitionTableResp();
 
     LOGGER.debug("GetSchemaPartition receive paths: {}, return: {}", relatedPaths, resp);
@@ -796,8 +791,7 @@ public class ConfigManager implements IManager {
     if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       return resp.setStatus(status);
     }
-    DataPartitionResp queryResult =
-        (DataPartitionResp) partitionManager.getDataPartition(getDataPartitionPlan);
+    DataPartitionResp queryResult = partitionManager.getDataPartition(getDataPartitionPlan);
 
     resp = queryResult.convertToTDataPartitionTableResp();
 
@@ -1137,7 +1131,7 @@ public class ConfigManager implements IManager {
       } catch (InterruptedException e) {
         Thread.currentThread().interrupt();
         LOGGER.warn("Unexpected interruption during retry creating peer for consensus group");
-      } catch (Exception e) {
+      } catch (ConsensusException e) {
         LOGGER.error("Failed to create peer for consensus group", e);
         break;
       }
@@ -1670,7 +1664,7 @@ public class ConfigManager implements IManager {
     TSStatus status = confirmLeader();
     return status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()
         ? pipeManager.getPipeTaskCoordinator().getAllPipeInfo()
-        : new TGetAllPipeInfoResp().setStatus(status);
+        : new TGetAllPipeInfoResp(status, Collections.emptyList());
   }
 
   @Override
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ModelManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ModelManager.java
index 425bafbd4c0..136d3849a88 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ModelManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ModelManager.java
@@ -36,8 +36,8 @@ import org.apache.iotdb.confignode.rpc.thrift.TShowTrailReq;
 import org.apache.iotdb.confignode.rpc.thrift.TShowTrailResp;
 import org.apache.iotdb.confignode.rpc.thrift.TUpdateModelInfoReq;
 import org.apache.iotdb.confignode.rpc.thrift.TUpdateModelStateReq;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.common.DataSet;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.slf4j.Logger;
@@ -79,52 +79,45 @@ public class ModelManager {
   }
 
   public TSStatus updateModelInfo(TUpdateModelInfoReq req) {
-    ConsensusWriteResponse response =
-        configManager.getConsensusManager().write(new UpdateModelInfoPlan(req));
-    if (response.getStatus() != null) {
-      return response.getStatus();
-    } else {
+    try {
+      return configManager.getConsensusManager().write(new UpdateModelInfoPlan(req));
+    } catch (ConsensusException e) {
       LOGGER.warn(
-          "Unexpected error happened while updating model {}: ",
-          req.getModelId(),
-          response.getException());
+          String.format("Unexpected error happened while updating model %s: ", req.getModelId()),
+          e);
       // consensus layer related errors
       TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
-      res.setMessage(response.getErrorMessage());
+      res.setMessage(e.getMessage());
       return res;
     }
   }
 
   public TSStatus updateModelState(TUpdateModelStateReq req) {
-    ConsensusWriteResponse response =
-        configManager.getConsensusManager().write(new UpdateModelStatePlan(req));
-    if (response.getStatus() != null) {
-      return response.getStatus();
-    } else {
+    try {
+      return configManager.getConsensusManager().write(new UpdateModelStatePlan(req));
+    } catch (ConsensusException e) {
       LOGGER.warn(
-          "Unexpected error happened while updating state of model {}: ",
-          req.getModelId(),
-          response.getException());
+          String.format(
+              "Unexpected error happened while updating state of model %s: ", req.getModelId()),
+          e);
       // consensus layer related errors
       TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
-      res.setMessage(response.getErrorMessage());
+      res.setMessage(e.getMessage());
       return res;
     }
   }
 
   public TShowModelResp showModel(TShowModelReq req) {
     try {
-      ConsensusReadResponse response =
-          configManager.getConsensusManager().read(new ShowModelPlan(req));
-      if (response.getDataset() != null) {
-        return ((ModelTableResp) response.getDataset()).convertToThriftResponse();
-      } else {
-        LOGGER.warn("Unexpected error happened while showing model: ", response.getException());
-        // consensus layer related errors
-        TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
-        res.setMessage(response.getException().toString());
-        return new TShowModelResp(res, Collections.emptyList());
-      }
+      DataSet response = configManager.getConsensusManager().read(new ShowModelPlan(req));
+      return ((ModelTableResp) response).convertToThriftResponse();
+    } catch (ConsensusException e) {
+      LOGGER.warn(
+          String.format("Unexpected error happened while showing model %s: ", req.getModelId()), e);
+      // consensus layer related errors
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new TShowModelResp(res, Collections.emptyList());
     } catch (IOException e) {
       LOGGER.error("Fail to get ModelTable", e);
       return new TShowModelResp(
@@ -136,17 +129,15 @@ public class ModelManager {
 
   public TShowTrailResp showTrail(TShowTrailReq req) {
     try {
-      ConsensusReadResponse response =
-          configManager.getConsensusManager().read(new ShowTrailPlan(req));
-      if (response.getDataset() != null) {
-        return ((TrailTableResp) response.getDataset()).convertToThriftResponse();
-      } else {
-        LOGGER.warn("Unexpected error happened while showing trail: ", response.getException());
-        // consensus layer related errors
-        TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
-        res.setMessage(response.getException().toString());
-        return new TShowTrailResp(res, Collections.emptyList());
-      }
+      DataSet response = configManager.getConsensusManager().read(new ShowTrailPlan(req));
+      return ((TrailTableResp) response).convertToThriftResponse();
+    } catch (ConsensusException e) {
+      LOGGER.warn(
+          String.format("Unexpected error happened while showing trail %s: ", req.getModelId()), e);
+      // consensus layer related errors
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new TShowTrailResp(res, Collections.emptyList());
     } catch (IOException e) {
       LOGGER.error("Fail to get TrailTable", e);
       return new TShowTrailResp(
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/PermissionManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/PermissionManager.java
index bfe0c3925fc..87878fb5b13 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/PermissionManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/PermissionManager.java
@@ -30,15 +30,22 @@ import org.apache.iotdb.confignode.consensus.response.auth.PermissionInfoResp;
 import org.apache.iotdb.confignode.manager.consensus.ConsensusManager;
 import org.apache.iotdb.confignode.persistence.AuthorInfo;
 import org.apache.iotdb.confignode.rpc.thrift.TPermissionInfoResp;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.mpp.rpc.thrift.TInvalidatePermissionCacheReq;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
 import java.util.List;
 
 /** Manager permission read and operation. */
 public class PermissionManager {
 
+  private static final Logger LOGGER = LoggerFactory.getLogger(PermissionManager.class);
+
   private final ConfigManager configManager;
   private final AuthorInfo authorInfo;
 
@@ -56,16 +63,23 @@ public class PermissionManager {
   public TSStatus operatePermission(AuthorPlan authorPlan) {
     TSStatus tsStatus;
     // If the permissions change, clear the cache content affected by the operation
-    if (authorPlan.getAuthorType() == ConfigPhysicalPlanType.CreateUser
-        || authorPlan.getAuthorType() == ConfigPhysicalPlanType.CreateRole) {
-      tsStatus = getConsensusManager().write(authorPlan).getStatus();
-    } else {
-      tsStatus = invalidateCache(authorPlan.getUserName(), authorPlan.getRoleName());
-      if (tsStatus.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        tsStatus = getConsensusManager().write(authorPlan).getStatus();
+    try {
+      if (authorPlan.getAuthorType() == ConfigPhysicalPlanType.CreateUser
+          || authorPlan.getAuthorType() == ConfigPhysicalPlanType.CreateRole) {
+        tsStatus = getConsensusManager().write(authorPlan);
+      } else {
+        tsStatus = invalidateCache(authorPlan.getUserName(), authorPlan.getRoleName());
+        if (tsStatus.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+          tsStatus = getConsensusManager().write(authorPlan);
+        }
       }
+      return tsStatus;
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return res;
     }
-    return tsStatus;
   }
 
   /**
@@ -75,7 +89,14 @@ public class PermissionManager {
    * @return PermissionInfoResp
    */
   public PermissionInfoResp queryPermission(AuthorPlan authorPlan) {
-    return (PermissionInfoResp) getConsensusManager().read(authorPlan).getDataset();
+    try {
+      return (PermissionInfoResp) getConsensusManager().read(authorPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new PermissionInfoResp(res, Collections.emptyMap());
+    }
   }
 
   private ConsensusManager getConsensusManager() {
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/TriggerManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/TriggerManager.java
index 1cb38042600..e1e1905fb62 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/TriggerManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/TriggerManager.java
@@ -47,6 +47,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TGetJarInListResp;
 import org.apache.iotdb.confignode.rpc.thrift.TGetLocationForTriggerResp;
 import org.apache.iotdb.confignode.rpc.thrift.TGetTriggerTableResp;
 import org.apache.iotdb.confignode.rpc.thrift.TTriggerState;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.mpp.rpc.thrift.TUpdateTriggerLocationReq;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
@@ -135,12 +136,9 @@ public class TriggerManager {
   public TGetTriggerTableResp getTriggerTable(boolean onlyStateful) {
     try {
       return ((TriggerTableResp)
-              configManager
-                  .getConsensusManager()
-                  .read(new GetTriggerTablePlan(onlyStateful))
-                  .getDataset())
+              configManager.getConsensusManager().read(new GetTriggerTablePlan(onlyStateful)))
           .convertToThriftResponse();
-    } catch (IOException e) {
+    } catch (IOException | ConsensusException e) {
       LOGGER.error("Fail to get TriggerTable", e);
       return new TGetTriggerTableResp(
           new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode())
@@ -150,21 +148,29 @@ public class TriggerManager {
   }
 
   public TGetLocationForTriggerResp getLocationOfStatefulTrigger(String triggerName) {
-    return ((TriggerLocationResp)
-            configManager
-                .getConsensusManager()
-                .read(new GetTriggerLocationPlan(triggerName))
-                .getDataset())
-        .convertToThriftResponse();
+    try {
+      return ((TriggerLocationResp)
+              configManager.getConsensusManager().read(new GetTriggerLocationPlan(triggerName)))
+          .convertToThriftResponse();
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read API executing the consensus layer due to: ", e);
+      return new TGetLocationForTriggerResp(
+          new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode())
+              .setMessage(e.getMessage()));
+    }
   }
 
   public TGetJarInListResp getTriggerJar(TGetJarInListReq req) {
-    return ((JarResp)
-            configManager
-                .getConsensusManager()
-                .read(new GetTriggerJarPlan(req.getJarNameList()))
-                .getDataset())
-        .convertToThriftResponse();
+    try {
+      return ((JarResp)
+              configManager.getConsensusManager().read(new GetTriggerJarPlan(req.getJarNameList())))
+          .convertToThriftResponse();
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new JarResp(res, Collections.emptyList()).convertToThriftResponse();
+    }
   }
 
   /**
@@ -191,16 +197,13 @@ public class TriggerManager {
       NodeManager nodeManager = configManager.getNodeManager();
 
       transferResult =
-          consensusManager
-              .write(new UpdateTriggersOnTransferNodesPlan(newUnknownDataNodeList))
-              .getStatus();
+          consensusManager.write(new UpdateTriggersOnTransferNodesPlan(newUnknownDataNodeList));
       if (transferResult.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return transferResult;
       }
 
       List<String> transferringTriggers =
-          ((TransferringTriggersResp)
-                  consensusManager.read(new GetTransferringTriggersPlan()).getDataset())
+          ((TransferringTriggersResp) consensusManager.read(new GetTransferringTriggersPlan()))
               .getTransferringTriggers();
 
       for (String trigger : transferringTriggers) {
@@ -215,13 +218,16 @@ public class TriggerManager {
         }
 
         transferResult =
-            consensusManager
-                .write(new UpdateTriggerLocationPlan(trigger, newDataNodeLocation))
-                .getStatus();
+            consensusManager.write(new UpdateTriggerLocationPlan(trigger, newDataNodeLocation));
         if (transferResult.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
           return transferResult;
         }
       }
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read/write API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return res;
     } finally {
       triggerInfo.releaseTriggerTableLock();
     }
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/UDFManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/UDFManager.java
index a7f5ef245b8..5e34a24311d 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/UDFManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/UDFManager.java
@@ -38,6 +38,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TCreateFunctionReq;
 import org.apache.iotdb.confignode.rpc.thrift.TGetJarInListReq;
 import org.apache.iotdb.confignode.rpc.thrift.TGetJarInListResp;
 import org.apache.iotdb.confignode.rpc.thrift.TGetUDFTableResp;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.mpp.rpc.thrift.TCreateFunctionInstanceReq;
 import org.apache.iotdb.mpp.rpc.thrift.TDropFunctionInstanceReq;
 import org.apache.iotdb.rpc.RpcUtils;
@@ -110,7 +111,7 @@ public class UDFManager {
 
       LOGGER.info("Start to add UDF [{}] in UDF_Table on Config Nodes", udfName);
 
-      return configManager.getConsensusManager().write(createFunctionPlan).getStatus();
+      return configManager.getConsensusManager().write(createFunctionPlan);
     } catch (Exception e) {
       LOGGER.warn(e.getMessage(), e);
       return new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode())
@@ -143,10 +144,7 @@ public class UDFManager {
         return result;
       }
 
-      return configManager
-          .getConsensusManager()
-          .write(new DropFunctionPlan(functionName))
-          .getStatus();
+      return configManager.getConsensusManager().write(new DropFunctionPlan(functionName));
     } catch (Exception e) {
       LOGGER.warn(e.getMessage(), e);
       return new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode())
@@ -171,9 +169,9 @@ public class UDFManager {
   public TGetUDFTableResp getUDFTable() {
     try {
       return ((FunctionTableResp)
-              configManager.getConsensusManager().read(new GetFunctionTablePlan()).getDataset())
+              configManager.getConsensusManager().read(new GetFunctionTablePlan()))
           .convertToThriftResponse();
-    } catch (IOException e) {
+    } catch (IOException | ConsensusException e) {
       LOGGER.error("Fail to get TriggerTable", e);
       return new TGetUDFTableResp(
           new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode())
@@ -183,11 +181,15 @@ public class UDFManager {
   }
 
   public TGetJarInListResp getUDFJar(TGetJarInListReq req) {
-    return ((JarResp)
-            configManager
-                .getConsensusManager()
-                .read(new GetUDFJarPlan(req.getJarNameList()))
-                .getDataset())
-        .convertToThriftResponse();
+    try {
+      return ((JarResp)
+              configManager.getConsensusManager().read(new GetUDFJarPlan(req.getJarNameList())))
+          .convertToThriftResponse();
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new JarResp(res, Collections.emptyList()).convertToThriftResponse();
+    }
   }
 }
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/consensus/ConsensusManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/consensus/ConsensusManager.java
index 6709d487139..16e90ee0712 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/consensus/ConsensusManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/consensus/ConsensusManager.java
@@ -38,11 +38,11 @@ import org.apache.iotdb.confignode.manager.IManager;
 import org.apache.iotdb.confignode.manager.node.NodeManager;
 import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.consensus.IConsensus;
+import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
 import org.apache.iotdb.consensus.config.RatisConfig;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.apache.ratis.util.SizeInBytes;
@@ -213,18 +213,26 @@ public class ConsensusManager {
           createPeerForConsensusGroup(SystemPropertiesUtils.loadConfigNodeList());
         } catch (BadNodeUrlException e) {
           throw new IOException(e);
+        } catch (ConsensusException e) {
+          LOGGER.error(
+              "Something wrong happened while calling consensus layer's createLocalPeer API.", e);
         }
       }
       LOGGER.info("Init ConsensusManager successfully when restarted");
     } else if (ConfigNodeDescriptor.getInstance().isSeedConfigNode()) {
       // Create ConsensusGroup that contains only itself
       // if the current ConfigNode is Seed-ConfigNode
-      createPeerForConsensusGroup(
-          Collections.singletonList(
-              new TConfigNodeLocation(
-                  SEED_CONFIG_NODE_ID,
-                  new TEndPoint(CONF.getInternalAddress(), CONF.getInternalPort()),
-                  new TEndPoint(CONF.getInternalAddress(), CONF.getConsensusPort()))));
+      try {
+        createPeerForConsensusGroup(
+            Collections.singletonList(
+                new TConfigNodeLocation(
+                    SEED_CONFIG_NODE_ID,
+                    new TEndPoint(CONF.getInternalAddress(), CONF.getInternalPort()),
+                    new TEndPoint(CONF.getInternalAddress(), CONF.getConsensusPort()))));
+      } catch (ConsensusException e) {
+        LOGGER.error(
+            "Something wrong happened while calling consensus layer's createLocalPeer API.", e);
+      }
     }
   }
 
@@ -249,8 +257,10 @@ public class ConsensusManager {
    * Create peer in new node to build consensus group.
    *
    * @param configNodeLocations All registered ConfigNodes
+   * @throws ConsensusException When addPeer doesn't success
    */
-  public void createPeerForConsensusGroup(List<TConfigNodeLocation> configNodeLocations) {
+  public void createPeerForConsensusGroup(List<TConfigNodeLocation> configNodeLocations)
+      throws ConsensusException {
     LOGGER.info("createPeerForConsensusGroup {}...", configNodeLocations);
 
     List<Peer> peerList = new ArrayList<>();
@@ -261,7 +271,7 @@ public class ConsensusManager {
               configNodeLocation.getConfigNodeId(),
               configNodeLocation.getConsensusEndPoint()));
     }
-    consensusImpl.createPeer(DEFAULT_CONSENSUS_GROUP_ID, peerList);
+    consensusImpl.createLocalPeer(DEFAULT_CONSENSUS_GROUP_ID, peerList);
   }
 
   /**
@@ -271,17 +281,14 @@ public class ConsensusManager {
    * @throws AddPeerException When addPeer doesn't success
    */
   public void addConfigNodePeer(TConfigNodeLocation configNodeLocation) throws AddPeerException {
-    boolean result =
-        consensusImpl
-            .addPeer(
-                DEFAULT_CONSENSUS_GROUP_ID,
-                new Peer(
-                    DEFAULT_CONSENSUS_GROUP_ID,
-                    configNodeLocation.getConfigNodeId(),
-                    configNodeLocation.getConsensusEndPoint()))
-            .isSuccess();
-
-    if (!result) {
+    try {
+      consensusImpl.addRemotePeer(
+          DEFAULT_CONSENSUS_GROUP_ID,
+          new Peer(
+              DEFAULT_CONSENSUS_GROUP_ID,
+              configNodeLocation.getConfigNodeId(),
+              configNodeLocation.getConsensusEndPoint()));
+    } catch (ConsensusException e) {
       throw new AddPeerException(configNodeLocation);
     }
   }
@@ -294,23 +301,34 @@ public class ConsensusManager {
    *     ConfigRegion
    */
   public boolean removeConfigNodePeer(TConfigNodeLocation configNodeLocation) {
-    return consensusImpl
-        .removePeer(
-            DEFAULT_CONSENSUS_GROUP_ID,
-            new Peer(
-                DEFAULT_CONSENSUS_GROUP_ID,
-                configNodeLocation.getConfigNodeId(),
-                configNodeLocation.getConsensusEndPoint()))
-        .isSuccess();
+    try {
+      consensusImpl.removeRemotePeer(
+          DEFAULT_CONSENSUS_GROUP_ID,
+          new Peer(
+              DEFAULT_CONSENSUS_GROUP_ID,
+              configNodeLocation.getConfigNodeId(),
+              configNodeLocation.getConsensusEndPoint()));
+      return true;
+    } catch (ConsensusException e) {
+      return false;
+    }
   }
 
-  /** Transmit PhysicalPlan to confignode.consensus.statemachine */
-  public ConsensusWriteResponse write(ConfigPhysicalPlan plan) {
+  /**
+   * Transmit PhysicalPlan to confignode.consensus.statemachine
+   *
+   * @throws ConsensusException When write doesn't success
+   */
+  public TSStatus write(ConfigPhysicalPlan plan) throws ConsensusException {
     return consensusImpl.write(DEFAULT_CONSENSUS_GROUP_ID, plan);
   }
 
-  /** Transmit PhysicalPlan to confignode.consensus.statemachine */
-  public ConsensusReadResponse read(ConfigPhysicalPlan plan) {
+  /**
+   * Transmit PhysicalPlan to confignode.consensus.statemachine
+   *
+   * @throws ConsensusException When read doesn't success
+   */
+  public DataSet read(ConfigPhysicalPlan plan) throws ConsensusException {
     return consensusImpl.read(DEFAULT_CONSENSUS_GROUP_ID, plan);
   }
 
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/cq/CQManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/cq/CQManager.java
index bbbae4f3b2e..cb7f9063965 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/cq/CQManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/cq/CQManager.java
@@ -33,8 +33,8 @@ import org.apache.iotdb.confignode.persistence.cq.CQInfo;
 import org.apache.iotdb.confignode.rpc.thrift.TCreateCQReq;
 import org.apache.iotdb.confignode.rpc.thrift.TDropCQReq;
 import org.apache.iotdb.confignode.rpc.thrift.TShowCQResp;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.common.DataSet;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.slf4j.Logger;
@@ -78,29 +78,26 @@ public class CQManager {
   }
 
   public TSStatus dropCQ(TDropCQReq req) {
-    ConsensusWriteResponse response =
-        configManager.getConsensusManager().write(new DropCQPlan(req.cqId));
-    if (response.getStatus() != null) {
-      return response.getStatus();
-    } else {
-      LOGGER.warn(
-          "Unexpected error happened while dropping cq {}: ", req.cqId, response.getException());
+    try {
+      return configManager.getConsensusManager().write(new DropCQPlan(req.cqId));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Unexpected error happened while dropping cq {}: ", req.cqId, e);
       // consensus layer related errors
       TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
-      res.setMessage(response.getErrorMessage());
+      res.setMessage(e.getMessage());
       return res;
     }
   }
 
   public TShowCQResp showCQ() {
-    ConsensusReadResponse response = configManager.getConsensusManager().read(new ShowCQPlan());
-    if (response.getDataset() != null) {
-      return ((ShowCQResp) response.getDataset()).convertToRpcShowCQResp();
-    } else {
-      LOGGER.warn("Unexpected error happened while showing cq: ", response.getException());
+    try {
+      DataSet response = configManager.getConsensusManager().read(new ShowCQPlan());
+      return ((ShowCQResp) response).convertToRpcShowCQResp();
+    } catch (ConsensusException e) {
+      LOGGER.warn("Unexpected error happened while showing cq: ", e);
       // consensus layer related errors
       TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
-      res.setMessage(response.getException().toString());
+      res.setMessage(e.getMessage());
       return new TShowCQResp(res, Collections.emptyList());
     }
   }
@@ -158,16 +155,15 @@ public class CQManager {
       }
       // keep fetching until we get all CQEntries if this node is still leader
       while (needFetch(allCQs)) {
-        ConsensusReadResponse response = configManager.getConsensusManager().read(new ShowCQPlan());
-        if (response.getDataset() != null) {
-          allCQs = ((ShowCQResp) response.getDataset()).getCqList();
-        } else {
+        try {
+          DataSet response = configManager.getConsensusManager().read(new ShowCQPlan());
+          allCQs = ((ShowCQResp) response).getCqList();
+        } catch (ConsensusException e) {
           // consensus layer related errors
-          LOGGER.warn(
-              "Unexpected error happened while fetching cq list: ", response.getException());
+          LOGGER.warn("Unexpected error happened while fetching cq list: ", e);
           try {
             Thread.sleep(500);
-          } catch (InterruptedException e) {
+          } catch (InterruptedException ie) {
             Thread.currentThread().interrupt();
           }
         }
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/cq/CQScheduleTask.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/cq/CQScheduleTask.java
index 5fa60c834c8..9ccd02f1281 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/cq/CQScheduleTask.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/cq/CQScheduleTask.java
@@ -29,7 +29,7 @@ import org.apache.iotdb.confignode.consensus.request.write.cq.UpdateCQLastExecTi
 import org.apache.iotdb.confignode.manager.ConfigManager;
 import org.apache.iotdb.confignode.persistence.cq.CQInfo;
 import org.apache.iotdb.confignode.rpc.thrift.TCreateCQReq;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.mpp.rpc.thrift.TExecuteCQ;
 import org.apache.iotdb.rpc.TSStatusCode;
 
@@ -245,24 +245,28 @@ public class CQScheduleTask implements Runnable {
             startTime,
             endTime,
             System.currentTimeMillis() * FACTOR);
-
-        ConsensusWriteResponse result =
-            configManager
-                .getConsensusManager()
-                .write(new UpdateCQLastExecTimePlan(cqId, executionTime, md5));
+        TSStatus result;
+        try {
+          result =
+              configManager
+                  .getConsensusManager()
+                  .write(new UpdateCQLastExecTimePlan(cqId, executionTime, md5));
+        } catch (ConsensusException e) {
+          result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+          result.setMessage(e.getMessage());
+        }
 
         // while leadership changed, the update last exec time operation for CQTasks in new leader
         // may still update failed because stale CQTask in old leader may update it in advance
-        if (!result.isSuccessful()) {
+        if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
           LOGGER.warn(
               "Failed to update the last execution time {} of CQ {}, because {}",
               executionTime,
               cqId,
-              result.getErrorMessage());
+              result.getMessage());
           // no such cq, we don't need to submit it again
-          if (result.getStatus() != null
-              && result.getStatus().code == TSStatusCode.NO_SUCH_CQ.getStatusCode()) {
-            LOGGER.info("Stop submitting CQ {} because {}", cqId, result.getStatus().message);
+          if (result.getCode() == TSStatusCode.NO_SUCH_CQ.getStatusCode()) {
+            LOGGER.info("Stop submitting CQ {} because {}", cqId, result.getMessage());
             return;
           }
         }
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/NodeManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/NodeManager.java
index 1ed797f6fdd..2b662573f08 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/NodeManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/node/NodeManager.java
@@ -76,8 +76,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TRuntimeConfiguration;
 import org.apache.iotdb.confignode.rpc.thrift.TSetDataNodeStatusReq;
 import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 
@@ -108,6 +107,9 @@ public class NodeManager {
 
   private final ReentrantLock removeConfigNodeLock;
 
+  private static final String CONSENSUS_WRITE_ERROR =
+      "Failed in the write API executing the consensus layer due to: ";
+
   public NodeManager(IManager configManager, NodeInfo nodeInfo) {
     this.configManager = configManager;
     this.nodeInfo = nodeInfo;
@@ -250,12 +252,20 @@ public class NodeManager {
         new RegisterDataNodePlan(req.getDataNodeConfiguration());
     // Register new DataNode
     registerDataNodePlan.getDataNodeConfiguration().getLocation().setDataNodeId(dataNodeId);
-    getConsensusManager().write(registerDataNodePlan);
+    try {
+      getConsensusManager().write(registerDataNodePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+    }
 
     // update datanode's versionInfo
     UpdateVersionInfoPlan updateVersionInfoPlan =
         new UpdateVersionInfoPlan(req.getVersionInfo(), dataNodeId);
-    getConsensusManager().write(updateVersionInfoPlan);
+    try {
+      getConsensusManager().write(updateVersionInfoPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+    }
 
     // Bind DataNode metrics
     PartitionMetrics.bindDataNodePartitionMetrics(
@@ -281,14 +291,22 @@ public class NodeManager {
       // Update DataNodeConfiguration when modified during restart
       UpdateDataNodePlan updateDataNodePlan =
           new UpdateDataNodePlan(req.getDataNodeConfiguration());
-      getConsensusManager().write(updateDataNodePlan);
+      try {
+        getConsensusManager().write(updateDataNodePlan);
+      } catch (ConsensusException e) {
+        LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      }
     }
     TNodeVersionInfo versionInfo = nodeInfo.getVersionInfo(nodeId);
     if (!req.getVersionInfo().equals(versionInfo)) {
       // Update versionInfo when modified during restart
       UpdateVersionInfoPlan updateVersionInfoPlan =
           new UpdateVersionInfoPlan(req.getVersionInfo(), nodeId);
-      getConsensusManager().write(updateVersionInfoPlan);
+      try {
+        getConsensusManager().write(updateVersionInfoPlan);
+      } catch (ConsensusException e) {
+        LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      }
     }
 
     TDataNodeRestartResp resp = new TDataNodeRestartResp();
@@ -363,11 +381,11 @@ public class NodeManager {
       // Update versionInfo when modified during restart
       UpdateVersionInfoPlan updateConfigNodePlan =
           new UpdateVersionInfoPlan(versionInfo, configNodeId);
-      ConsensusWriteResponse result = getConsensusManager().write(updateConfigNodePlan);
-      if (result.getException() != null) {
+      try {
+        return getConsensusManager().write(updateConfigNodePlan);
+      } catch (ConsensusException e) {
         return new TSStatus(TSStatusCode.CONSENSUS_NOT_INITIALIZED.getStatusCode());
       }
-      return result.getStatus();
     }
     return ClusterNodeStartUtils.ACCEPT_NODE_RESTART;
   }
@@ -380,7 +398,16 @@ public class NodeManager {
    *     GetDataNodeConfigurationPlan is -1
    */
   public DataNodeConfigurationResp getDataNodeConfiguration(GetDataNodeConfigurationPlan req) {
-    return (DataNodeConfigurationResp) getConsensusManager().read(req).getDataset();
+    try {
+      return (DataNodeConfigurationResp) getConsensusManager().read(req);
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      DataNodeConfigurationResp response = new DataNodeConfigurationResp();
+      response.setStatus(res);
+      return response;
+    }
   }
 
   /**
@@ -526,10 +553,18 @@ public class NodeManager {
   public void applyConfigNode(
       TConfigNodeLocation configNodeLocation, TNodeVersionInfo versionInfo) {
     ApplyConfigNodePlan applyConfigNodePlan = new ApplyConfigNodePlan(configNodeLocation);
-    getConsensusManager().write(applyConfigNodePlan);
+    try {
+      getConsensusManager().write(applyConfigNodePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+    }
     UpdateVersionInfoPlan updateVersionInfoPlan =
         new UpdateVersionInfoPlan(versionInfo, configNodeLocation.getConfigNodeId());
-    getConsensusManager().write(updateVersionInfoPlan);
+    try {
+      getConsensusManager().write(updateVersionInfoPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+    }
   }
 
   /**
@@ -590,13 +625,13 @@ public class NodeManager {
           .setMessage(
               "Transfer ConfigNode leader failed because can not find any running ConfigNode.");
     }
-    ConsensusGenericResponse resp =
-        getConsensusManager()
-            .getConsensusImpl()
-            .transferLeader(
-                groupId,
-                new Peer(groupId, newLeader.getConfigNodeId(), newLeader.getConsensusEndPoint()));
-    if (!resp.isSuccess()) {
+    try {
+      getConsensusManager()
+          .getConsensusImpl()
+          .transferLeader(
+              groupId,
+              new Peer(groupId, newLeader.getConfigNodeId(), newLeader.getConsensusEndPoint()));
+    } catch (ConsensusException e) {
       return new TSStatus(TSStatusCode.REMOVE_CONFIGNODE_ERROR.getStatusCode())
           .setMessage("Remove ConfigNode failed because transfer ConfigNode leader failed.");
     }
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
index ac0df2916a9..f4ef35f146d 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
@@ -84,9 +84,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TGetRegionIdReq;
 import org.apache.iotdb.confignode.rpc.thrift.TGetSeriesSlotListReq;
 import org.apache.iotdb.confignode.rpc.thrift.TGetTimeSlotListReq;
 import org.apache.iotdb.confignode.rpc.thrift.TTimeSlotList;
-import org.apache.iotdb.consensus.common.DataSet;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.mpp.rpc.thrift.TCreateDataRegionReq;
 import org.apache.iotdb.mpp.rpc.thrift.TCreateSchemaRegionReq;
 import org.apache.iotdb.rpc.RpcUtils;
@@ -97,6 +95,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -131,6 +130,12 @@ public class PartitionManager {
 
   private SeriesPartitionExecutor executor;
 
+  private static final String CONSENSUS_READ_ERROR =
+      "Failed in the read API executing the consensus layer due to: ";
+
+  private static final String CONSENSUS_WRITE_ERROR =
+      "Failed in the write API executing the consensus layer due to: ";
+
   /** Region cleaner. */
   // Monitor for leadership change
   private final Object scheduleMonitor = new Object();
@@ -165,8 +170,15 @@ public class PartitionManager {
    * @param req SchemaPartitionPlan with partitionSlotsMap
    * @return SchemaPartitionDataSet that contains only existing SchemaPartition
    */
-  public DataSet getSchemaPartition(GetSchemaPartitionPlan req) {
-    return getConsensusManager().read(req).getDataset();
+  public SchemaPartitionResp getSchemaPartition(GetSchemaPartitionPlan req) {
+    try {
+      return (SchemaPartitionResp) getConsensusManager().read(req);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new SchemaPartitionResp(res, false, Collections.emptyMap());
+    }
   }
 
   /**
@@ -176,8 +188,15 @@ public class PartitionManager {
    *     TTimeSlotList>>
    * @return DataPartitionDataSet that contains only existing DataPartition
    */
-  public DataSet getDataPartition(GetDataPartitionPlan req) {
-    return getConsensusManager().read(req).getDataset();
+  public DataPartitionResp getDataPartition(GetDataPartitionPlan req) {
+    try {
+      return (DataPartitionResp) getConsensusManager().read(req);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new DataPartitionResp(res, false, Collections.emptyMap());
+    }
   }
 
   /**
@@ -205,7 +224,7 @@ public class PartitionManager {
 
     // After all the SchemaPartitions are allocated,
     // all the read requests about SchemaPartitionTable are parallel.
-    SchemaPartitionResp resp = (SchemaPartitionResp) getSchemaPartition(req);
+    SchemaPartitionResp resp = getSchemaPartition(req);
     if (resp.isAllPartitionsExist()) {
       return resp;
     }
@@ -218,7 +237,7 @@ public class PartitionManager {
     synchronized (this) {
       // Here we should check again if the SchemaPartition
       // has been created by other threads to improve concurrent performance
-      resp = (SchemaPartitionResp) getSchemaPartition(req);
+      resp = getSchemaPartition(req);
       if (resp.isAllPartitionsExist()) {
         return resp;
       }
@@ -276,7 +295,7 @@ public class PartitionManager {
       }
     }
 
-    resp = (SchemaPartitionResp) getSchemaPartition(req);
+    resp = getSchemaPartition(req);
     if (!resp.isAllPartitionsExist()) {
       // Count the fail rate
       AtomicInteger totalSlotNum = new AtomicInteger();
@@ -328,7 +347,7 @@ public class PartitionManager {
 
     // After all the DataPartitions are allocated,
     // all the read requests about DataPartitionTable are parallel.
-    DataPartitionResp resp = (DataPartitionResp) getDataPartition(req);
+    DataPartitionResp resp = getDataPartition(req);
     if (resp.isAllPartitionsExist()) {
       return resp;
     }
@@ -341,7 +360,7 @@ public class PartitionManager {
     synchronized (this) {
       // Here we should check again if the DataPartition
       // has been created by other threads to improve concurrent performance
-      resp = (DataPartitionResp) getDataPartition(req);
+      resp = getDataPartition(req);
       if (resp.isAllPartitionsExist()) {
         return resp;
       }
@@ -399,7 +418,7 @@ public class PartitionManager {
       }
     }
 
-    resp = (DataPartitionResp) getDataPartition(req);
+    resp = getDataPartition(req);
     if (!resp.isAllPartitionsExist()) {
       // Count the fail rate
       AtomicInteger totalSlotNum = new AtomicInteger();
@@ -438,15 +457,15 @@ public class PartitionManager {
       // since the RegionGroup creating process might take some time
       return status;
     }
-
-    ConsensusWriteResponse writeResp = getConsensusManager().write(plan);
-    if (!writeResp.isSuccessful()) {
+    try {
+      return getConsensusManager().write(plan);
+    } catch (ConsensusException e) {
       // The allocation might fail due to consensus error
-      status = writeResp.getStatus();
-      status.setMessage(writeResp.getErrorMessage());
       LOGGER.error("Write DataPartition allocation result failed because: {}", status);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return res;
     }
-    return status;
   }
 
   // ======================================================
@@ -886,17 +905,27 @@ public class PartitionManager {
    *     SchemaPartition and matched child paths aboveMTree
    */
   public SchemaNodeManagementResp getNodePathsPartition(GetNodePathsPartitionPlan physicalPlan) {
-    SchemaNodeManagementResp schemaNodeManagementResp;
-    ConsensusReadResponse consensusReadResponse = getConsensusManager().read(physicalPlan);
-    schemaNodeManagementResp = (SchemaNodeManagementResp) consensusReadResponse.getDataset();
-    return schemaNodeManagementResp;
+    try {
+      return (SchemaNodeManagementResp) getConsensusManager().read(physicalPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      SchemaNodeManagementResp resp = new SchemaNodeManagementResp();
+      resp.setStatus(res);
+      return resp;
+    }
   }
 
   public void preDeleteDatabase(
       String database, PreDeleteDatabasePlan.PreDeleteType preDeleteType) {
     final PreDeleteDatabasePlan preDeleteDatabasePlan =
         new PreDeleteDatabasePlan(database, preDeleteType);
-    getConsensusManager().write(preDeleteDatabasePlan);
+    try {
+      getConsensusManager().write(preDeleteDatabasePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+    }
   }
 
   public boolean isDatabasePreDeleted(String database) {
@@ -914,30 +943,39 @@ public class PartitionManager {
   }
 
   public RegionInfoListResp getRegionInfoList(GetRegionInfoListPlan req) {
-    // Get static result
-    RegionInfoListResp regionInfoListResp =
-        (RegionInfoListResp) getConsensusManager().read(req).getDataset();
-
-    // Get cached result
-    Map<TConsensusGroupId, Integer> allLeadership = getLoadManager().getRegionLeaderMap();
-    regionInfoListResp
-        .getRegionInfoList()
-        .forEach(
-            regionInfo -> {
-              regionInfo.setStatus(
-                  getLoadManager()
-                      .getRegionStatus(regionInfo.getConsensusGroupId(), regionInfo.getDataNodeId())
-                      .getStatus());
-
-              String regionType =
-                  regionInfo.getDataNodeId()
-                          == allLeadership.getOrDefault(regionInfo.getConsensusGroupId(), -1)
-                      ? RegionRoleType.Leader.toString()
-                      : RegionRoleType.Follower.toString();
-              regionInfo.setRoleType(regionType);
-            });
-
-    return regionInfoListResp;
+    try {
+      // Get static result
+      RegionInfoListResp regionInfoListResp = (RegionInfoListResp) getConsensusManager().read(req);
+      // Get cached result
+      Map<TConsensusGroupId, Integer> allLeadership = getLoadManager().getRegionLeaderMap();
+      regionInfoListResp
+          .getRegionInfoList()
+          .forEach(
+              regionInfo -> {
+                regionInfo.setStatus(
+                    getLoadManager()
+                        .getRegionStatus(
+                            regionInfo.getConsensusGroupId(), regionInfo.getDataNodeId())
+                        .getStatus());
+
+                String regionType =
+                    regionInfo.getDataNodeId()
+                            == allLeadership.getOrDefault(regionInfo.getConsensusGroupId(), -1)
+                        ? RegionRoleType.Leader.toString()
+                        : RegionRoleType.Follower.toString();
+                regionInfo.setRoleType(regionType);
+              });
+
+      return regionInfoListResp;
+
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      RegionInfoListResp resp = new RegionInfoListResp();
+      resp.setStatus(res);
+      return resp;
+    }
   }
 
   /**
@@ -956,7 +994,14 @@ public class PartitionManager {
    * @return TSStatus
    */
   public TSStatus updateRegionLocation(UpdateRegionLocationPlan req) {
-    return getConsensusManager().write(req).getStatus();
+    try {
+      return getConsensusManager().write(req);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return res;
+    }
   }
 
   public GetRegionIdResp getRegionId(TGetRegionIdReq req) {
@@ -977,7 +1022,14 @@ public class PartitionManager {
           new TTimePartitionSlot(
               req.getTimeStamp() - req.getTimeStamp() % COMMON_CONFIG.getTimePartitionInterval()));
     }
-    return (GetRegionIdResp) getConsensusManager().read(plan).getDataset();
+    try {
+      return (GetRegionIdResp) getConsensusManager().read(plan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new GetRegionIdResp(res, Collections.emptyList());
+    }
   }
 
   public GetTimeSlotListResp getTimeSlotList(TGetTimeSlotListReq req) {
@@ -997,7 +1049,14 @@ public class PartitionManager {
       plan.setRegionId(
           new TConsensusGroupId(TConsensusGroupType.DataRegion, (int) req.getRegionId()));
     }
-    return (GetTimeSlotListResp) getConsensusManager().read(plan).getDataset();
+    try {
+      return (GetTimeSlotListResp) getConsensusManager().read(plan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new GetTimeSlotListResp(res, Collections.emptyList());
+    }
   }
 
   public CountTimeSlotListResp countTimeSlotList(TCountTimeSlotListReq req) {
@@ -1017,12 +1076,26 @@ public class PartitionManager {
       plan.setRegionId(
           new TConsensusGroupId(TConsensusGroupType.DataRegion, (int) req.getRegionId()));
     }
-    return (CountTimeSlotListResp) getConsensusManager().read(plan).getDataset();
+    try {
+      return (CountTimeSlotListResp) getConsensusManager().read(plan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new CountTimeSlotListResp(res, 0);
+    }
   }
 
   public GetSeriesSlotListResp getSeriesSlotList(TGetSeriesSlotListReq req) {
     GetSeriesSlotListPlan plan = new GetSeriesSlotListPlan(req.getDatabase(), req.getType());
-    return (GetSeriesSlotListResp) getConsensusManager().read(plan).getDataset();
+    try {
+      return (GetSeriesSlotListResp) getConsensusManager().read(plan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new GetSeriesSlotListResp(res, Collections.emptyList());
+    }
   }
 
   /**
@@ -1233,8 +1306,12 @@ public class PartitionManager {
                   }
 
                   // Poll the head entry if success
-                  getConsensusManager()
-                      .write(new PollSpecificRegionMaintainTaskPlan(successfulTask));
+                  try {
+                    getConsensusManager()
+                        .write(new PollSpecificRegionMaintainTaskPlan(successfulTask));
+                  } catch (ConsensusException e) {
+                    LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+                  }
 
                   if (successfulTask.size() < selectedRegionMaintainTask.size()) {
                     // Here we just break and wait until next schedule task
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/plugin/PipePluginCoordinator.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/plugin/PipePluginCoordinator.java
index 6fb9e93a0d8..620aaa27ca2 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/plugin/PipePluginCoordinator.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/plugin/PipePluginCoordinator.java
@@ -31,6 +31,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TCreatePipePluginReq;
 import org.apache.iotdb.confignode.rpc.thrift.TGetJarInListReq;
 import org.apache.iotdb.confignode.rpc.thrift.TGetJarInListResp;
 import org.apache.iotdb.confignode.rpc.thrift.TGetPipePluginTableResp;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.slf4j.Logger;
@@ -81,9 +82,9 @@ public class PipePluginCoordinator {
   public TGetPipePluginTableResp getPipePluginTable() {
     try {
       return ((PipePluginTableResp)
-              configManager.getConsensusManager().read(new GetPipePluginTablePlan()).getDataset())
+              configManager.getConsensusManager().read(new GetPipePluginTablePlan()))
           .convertToThriftResponse();
-    } catch (IOException e) {
+    } catch (IOException | ConsensusException e) {
       LOGGER.error("Fail to get PipePluginTable", e);
       return new TGetPipePluginTableResp(
           new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode())
@@ -93,11 +94,17 @@ public class PipePluginCoordinator {
   }
 
   public TGetJarInListResp getPipePluginJar(TGetJarInListReq req) {
-    return ((JarResp)
-            configManager
-                .getConsensusManager()
-                .read(new GetPipePluginJarPlan(req.getJarNameList()))
-                .getDataset())
-        .convertToThriftResponse();
+    try {
+      return ((JarResp)
+              configManager
+                  .getConsensusManager()
+                  .read(new GetPipePluginJarPlan(req.getJarNameList())))
+          .convertToThriftResponse();
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new JarResp(res, Collections.emptyList()).convertToThriftResponse();
+    }
   }
 }
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/task/PipeTaskCoordinator.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/task/PipeTaskCoordinator.java
index 886a728916b..832f6a1a84a 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/task/PipeTaskCoordinator.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/task/PipeTaskCoordinator.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TCreatePipeReq;
 import org.apache.iotdb.confignode.rpc.thrift.TGetAllPipeInfoResp;
 import org.apache.iotdb.confignode.rpc.thrift.TShowPipeReq;
 import org.apache.iotdb.confignode.rpc.thrift.TShowPipeResp;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 
@@ -141,10 +142,14 @@ public class PipeTaskCoordinator {
   public TShowPipeResp showPipes(TShowPipeReq req) {
     lock();
     try {
-      return ((PipeTableResp)
-              configManager.getConsensusManager().read(new ShowPipePlanV2()).getDataset())
+      return ((PipeTableResp) configManager.getConsensusManager().read(new ShowPipePlanV2()))
           .filter(req.whereClause, req.pipeName)
           .convertToTShowPipeResp();
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return new PipeTableResp(res, Collections.emptyList()).convertToTShowPipeResp();
     } finally {
       unlock();
     }
@@ -153,10 +158,9 @@ public class PipeTaskCoordinator {
   public TGetAllPipeInfoResp getAllPipeInfo() {
     lock();
     try {
-      return ((PipeTableResp)
-              configManager.getConsensusManager().read(new ShowPipePlanV2()).getDataset())
+      return ((PipeTableResp) configManager.getConsensusManager().read(new ShowPipePlanV2()))
           .convertToTGetAllPipeInfoResp();
-    } catch (IOException e) {
+    } catch (IOException | ConsensusException e) {
       LOGGER.warn("Failed to get all pipe info.", e);
       return new TGetAllPipeInfoResp(
           new TSStatus(TSStatusCode.PIPE_ERROR.getStatusCode()).setMessage(e.getMessage()),
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
index 808627fd82c..dfacde2296c 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.iotdb.confignode.manager.schema;
 
 import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
@@ -72,6 +73,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
 import org.apache.iotdb.confignode.rpc.thrift.TGetPathsSetTemplatesResp;
 import org.apache.iotdb.confignode.rpc.thrift.TGetTemplateResp;
 import org.apache.iotdb.confignode.rpc.thrift.TShowDatabaseResp;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.exception.metadata.DatabaseAlreadySetException;
 import org.apache.iotdb.db.exception.metadata.SchemaQuotaExceededException;
@@ -113,6 +115,12 @@ public class ClusterSchemaManager {
   private final ClusterSchemaQuotaStatistics schemaQuotaStatistics;
   private final ReentrantLock createDatabaseLock = new ReentrantLock();
 
+  private static final String CONSENSUS_READ_ERROR =
+      "Failed in the read API executing the consensus layer due to: ";
+
+  private static final String CONSENSUS_WRITE_ERROR =
+      "Failed in the write API executing the consensus layer due to: ";
+
   public ClusterSchemaManager(
       IManager configManager,
       ClusterSchemaInfo clusterSchemaInfo,
@@ -152,12 +160,16 @@ public class ClusterSchemaManager {
         clusterSchemaInfo.checkDatabaseLimit();
       }
       // Cache DatabaseSchema
-      result = getConsensusManager().write(databaseSchemaPlan).getStatus();
+      result = getConsensusManager().write(databaseSchemaPlan);
       // Bind Database metrics
       PartitionMetrics.bindDatabasePartitionMetrics(
           MetricService.getInstance(), configManager, databaseSchemaPlan.getSchema().getName());
       // Adjust the maximum RegionGroup number of each Database
       adjustMaxRegionGroupNum();
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
     } catch (MetadataException metadataException) {
       // Reject if StorageGroup already set
       if (metadataException instanceof IllegalPathException) {
@@ -220,12 +232,26 @@ public class ClusterSchemaManager {
     }
 
     // Alter DatabaseSchema
-    return getConsensusManager().write(databaseSchemaPlan).getStatus();
+    try {
+      return getConsensusManager().write(databaseSchemaPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+      return result;
+    }
   }
 
   /** Delete DatabaseSchema. */
   public TSStatus deleteDatabase(DeleteDatabasePlan deleteDatabasePlan) {
-    TSStatus result = getConsensusManager().write(deleteDatabasePlan).getStatus();
+    TSStatus result;
+    try {
+      result = getConsensusManager().write(deleteDatabasePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+    }
     if (result.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       adjustMaxRegionGroupNum();
     }
@@ -240,7 +266,16 @@ public class ClusterSchemaManager {
    * @return CountDatabaseResp
    */
   public CountDatabaseResp countMatchedDatabases(CountDatabasePlan countDatabasePlan) {
-    return (CountDatabaseResp) getConsensusManager().read(countDatabasePlan).getDataset();
+    try {
+      return (CountDatabaseResp) getConsensusManager().read(countDatabasePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      CountDatabaseResp response = new CountDatabaseResp();
+      response.setStatus(res);
+      return response;
+    }
   }
 
   /**
@@ -251,8 +286,16 @@ public class ClusterSchemaManager {
    * @return DatabaseSchemaResp
    */
   public DatabaseSchemaResp getMatchedDatabaseSchema(GetDatabasePlan getStorageGroupPlan) {
-    DatabaseSchemaResp resp =
-        (DatabaseSchemaResp) getConsensusManager().read(getStorageGroupPlan).getDataset();
+    DatabaseSchemaResp resp;
+    try {
+      resp = (DatabaseSchemaResp) getConsensusManager().read(getStorageGroupPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      resp = new DatabaseSchemaResp();
+      resp.setStatus(res);
+    }
     List<String> preDeletedDatabaseList = new ArrayList<>();
     for (String database : resp.getSchemaMap().keySet()) {
       if (getPartitionManager().isDatabasePreDeleted(database)) {
@@ -267,8 +310,16 @@ public class ClusterSchemaManager {
 
   /** Only used in cluster tool show Databases. */
   public TShowDatabaseResp showDatabase(GetDatabasePlan getStorageGroupPlan) {
-    DatabaseSchemaResp databaseSchemaResp =
-        (DatabaseSchemaResp) getConsensusManager().read(getStorageGroupPlan).getDataset();
+    DatabaseSchemaResp databaseSchemaResp;
+    try {
+      databaseSchemaResp = (DatabaseSchemaResp) getConsensusManager().read(getStorageGroupPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      databaseSchemaResp = new DatabaseSchemaResp();
+      databaseSchemaResp.setStatus(res);
+    }
     if (databaseSchemaResp.getStatus().getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       // Return immediately if some Database doesn't exist
       return new TShowDatabaseResp().setStatus(databaseSchemaResp.getStatus());
@@ -374,25 +425,53 @@ public class ClusterSchemaManager {
     // TODO: Check response
     AsyncDataNodeClientPool.getInstance().sendAsyncRequestToDataNodeWithRetry(clientHandler);
 
-    return getConsensusManager().write(setTTLPlan).getStatus();
+    try {
+      return getConsensusManager().write(setTTLPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+      return result;
+    }
   }
 
   public TSStatus setSchemaReplicationFactor(
       SetSchemaReplicationFactorPlan setSchemaReplicationFactorPlan) {
     // TODO: Inform DataNodes
-    return getConsensusManager().write(setSchemaReplicationFactorPlan).getStatus();
+    try {
+      return getConsensusManager().write(setSchemaReplicationFactorPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+      return result;
+    }
   }
 
   public TSStatus setDataReplicationFactor(
       SetDataReplicationFactorPlan setDataReplicationFactorPlan) {
     // TODO: Inform DataNodes
-    return getConsensusManager().write(setDataReplicationFactorPlan).getStatus();
+    try {
+      return getConsensusManager().write(setDataReplicationFactorPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+      return result;
+    }
   }
 
   public TSStatus setTimePartitionInterval(
       SetTimePartitionIntervalPlan setTimePartitionIntervalPlan) {
     // TODO: Inform DataNodes
-    return getConsensusManager().write(setTimePartitionIntervalPlan).getStatus();
+    try {
+      return getConsensusManager().write(setTimePartitionIntervalPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+      return result;
+    }
   }
 
   /**
@@ -478,7 +557,11 @@ public class ClusterSchemaManager {
         LOGGER.warn("Adjust maxRegionGroupNum failed because StorageGroup doesn't exist", e);
       }
     }
-    getConsensusManager().write(adjustMaxRegionGroupNumPlan);
+    try {
+      getConsensusManager().write(adjustMaxRegionGroupNumPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+    }
   }
 
   public static int calcMaxRegionGroupNum(
@@ -632,7 +715,14 @@ public class ClusterSchemaManager {
    * @return TSStatus
    */
   public TSStatus createTemplate(CreateSchemaTemplatePlan createSchemaTemplatePlan) {
-    return getConsensusManager().write(createSchemaTemplatePlan).getStatus();
+    try {
+      return getConsensusManager().write(createSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      return res;
+    }
   }
 
   /**
@@ -642,8 +732,16 @@ public class ClusterSchemaManager {
    */
   public TGetAllTemplatesResp getAllTemplates() {
     GetAllSchemaTemplatePlan getAllSchemaTemplatePlan = new GetAllSchemaTemplatePlan();
-    TemplateInfoResp templateResp =
-        (TemplateInfoResp) getConsensusManager().read(getAllSchemaTemplatePlan).getDataset();
+    TemplateInfoResp templateResp;
+    try {
+      templateResp = (TemplateInfoResp) getConsensusManager().read(getAllSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      templateResp = new TemplateInfoResp();
+      templateResp.setStatus(res);
+    }
     TGetAllTemplatesResp resp = new TGetAllTemplatesResp();
     resp.setStatus(templateResp.getStatus());
     if (resp.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()
@@ -658,8 +756,16 @@ public class ClusterSchemaManager {
   /** show nodes in schemaengine template */
   public TGetTemplateResp getTemplate(String req) {
     GetSchemaTemplatePlan getSchemaTemplatePlan = new GetSchemaTemplatePlan(req);
-    TemplateInfoResp templateResp =
-        (TemplateInfoResp) getConsensusManager().read(getSchemaTemplatePlan).getDataset();
+    TemplateInfoResp templateResp;
+    try {
+      templateResp = (TemplateInfoResp) getConsensusManager().read(getSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      templateResp = new TemplateInfoResp();
+      templateResp.setStatus(res);
+    }
     TGetTemplateResp resp = new TGetTemplateResp();
     if (templateResp.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()
         && templateResp.getTemplateList() != null
@@ -674,8 +780,16 @@ public class ClusterSchemaManager {
   /** show path set template xx */
   public TGetPathsSetTemplatesResp getPathsSetTemplate(String templateName) {
     GetPathsSetTemplatePlan getPathsSetTemplatePlan = new GetPathsSetTemplatePlan(templateName);
-    PathInfoResp pathInfoResp =
-        (PathInfoResp) getConsensusManager().read(getPathsSetTemplatePlan).getDataset();
+    PathInfoResp pathInfoResp;
+    try {
+      pathInfoResp = (PathInfoResp) getConsensusManager().read(getPathsSetTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      pathInfoResp = new PathInfoResp();
+      pathInfoResp.setStatus(res);
+    }
     if (pathInfoResp.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       TGetPathsSetTemplatesResp resp = new TGetPathsSetTemplatesResp();
       resp.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
@@ -691,21 +805,42 @@ public class ClusterSchemaManager {
    * template info won't be taken
    */
   public byte[] getAllTemplateSetInfo() {
-    AllTemplateSetInfoResp resp =
-        (AllTemplateSetInfoResp)
-            getConsensusManager().read(new GetAllTemplateSetInfoPlan()).getDataset();
-    return resp.getTemplateInfo();
+    try {
+      AllTemplateSetInfoResp resp =
+          (AllTemplateSetInfoResp) getConsensusManager().read(new GetAllTemplateSetInfoPlan());
+      return resp.getTemplateInfo();
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      return new byte[0];
+    }
   }
 
   public TemplateSetInfoResp getTemplateSetInfo(List<PartialPath> patternList) {
-    return (TemplateSetInfoResp)
-        getConsensusManager().read(new GetTemplateSetInfoPlan(patternList)).getDataset();
+    try {
+      return (TemplateSetInfoResp)
+          getConsensusManager().read(new GetTemplateSetInfoPlan(patternList));
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      TemplateSetInfoResp response = new TemplateSetInfoResp();
+      response.setStatus(res);
+      return response;
+    }
   }
 
   public Pair<TSStatus, Template> checkIsTemplateSetOnPath(String templateName, String path) {
     GetSchemaTemplatePlan getSchemaTemplatePlan = new GetSchemaTemplatePlan(templateName);
-    TemplateInfoResp templateResp =
-        (TemplateInfoResp) getConsensusManager().read(getSchemaTemplatePlan).getDataset();
+    TemplateInfoResp templateResp;
+    try {
+      templateResp = (TemplateInfoResp) getConsensusManager().read(getSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      templateResp = new TemplateInfoResp();
+      templateResp.setStatus(res);
+    }
     if (templateResp.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       if (templateResp.getTemplateList() == null || templateResp.getTemplateList().isEmpty()) {
         return new Pair<>(
@@ -719,8 +854,16 @@ public class ClusterSchemaManager {
     }
 
     GetPathsSetTemplatePlan getPathsSetTemplatePlan = new GetPathsSetTemplatePlan(templateName);
-    PathInfoResp pathInfoResp =
-        (PathInfoResp) getConsensusManager().read(getPathsSetTemplatePlan).getDataset();
+    PathInfoResp pathInfoResp;
+    try {
+      pathInfoResp = (PathInfoResp) getConsensusManager().read(getPathsSetTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      pathInfoResp = new PathInfoResp();
+      pathInfoResp.setStatus(res);
+    }
     if (pathInfoResp.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       List<String> templateSetPathList = pathInfoResp.getPathList();
       if (templateSetPathList == null
@@ -740,27 +883,52 @@ public class ClusterSchemaManager {
   }
 
   public TSStatus preUnsetSchemaTemplate(int templateId, PartialPath path) {
-    return getConsensusManager()
-        .write(new PreUnsetSchemaTemplatePlan(templateId, path))
-        .getStatus();
+    try {
+      return getConsensusManager().write(new PreUnsetSchemaTemplatePlan(templateId, path));
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+      return result;
+    }
   }
 
   public TSStatus rollbackPreUnsetSchemaTemplate(int templateId, PartialPath path) {
-    return getConsensusManager()
-        .write(new RollbackPreUnsetSchemaTemplatePlan(templateId, path))
-        .getStatus();
+    try {
+      return getConsensusManager().write(new RollbackPreUnsetSchemaTemplatePlan(templateId, path));
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+      return result;
+    }
   }
 
   public TSStatus unsetSchemaTemplateInBlackList(int templateId, PartialPath path) {
-    return getConsensusManager().write(new UnsetSchemaTemplatePlan(templateId, path)).getStatus();
+    try {
+      return getConsensusManager().write(new UnsetSchemaTemplatePlan(templateId, path));
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+      return result;
+    }
   }
 
   public synchronized TSStatus dropSchemaTemplate(String templateName) {
 
     // check template existence
     GetSchemaTemplatePlan getSchemaTemplatePlan = new GetSchemaTemplatePlan(templateName);
-    TemplateInfoResp templateInfoResp =
-        (TemplateInfoResp) getConsensusManager().read(getSchemaTemplatePlan).getDataset();
+    TemplateInfoResp templateInfoResp;
+    try {
+      templateInfoResp = (TemplateInfoResp) getConsensusManager().read(getSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      templateInfoResp = new TemplateInfoResp();
+      templateInfoResp.setStatus(res);
+    }
     if (templateInfoResp.getStatus().getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       return templateInfoResp.getStatus();
     } else if (templateInfoResp.getTemplateList() == null
@@ -772,8 +940,16 @@ public class ClusterSchemaManager {
 
     // check is template set on some path, block all template set operation
     GetPathsSetTemplatePlan getPathsSetTemplatePlan = new GetPathsSetTemplatePlan(templateName);
-    PathInfoResp pathInfoResp =
-        (PathInfoResp) getConsensusManager().read(getPathsSetTemplatePlan).getDataset();
+    PathInfoResp pathInfoResp;
+    try {
+      pathInfoResp = (PathInfoResp) getConsensusManager().read(getPathsSetTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_READ_ERROR, e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      pathInfoResp = new PathInfoResp();
+      pathInfoResp.setStatus(res);
+    }
     if (pathInfoResp.getStatus().getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       return pathInfoResp.getStatus();
     } else if (pathInfoResp.getPathList() != null && !pathInfoResp.getPathList().isEmpty()) {
@@ -784,7 +960,14 @@ public class ClusterSchemaManager {
     }
 
     // execute drop template
-    return getConsensusManager().write(new DropSchemaTemplatePlan(templateName)).getStatus();
+    try {
+      return getConsensusManager().write(new DropSchemaTemplatePlan(templateName));
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      TSStatus result = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      result.setMessage(e.getMessage());
+      return result;
+    }
   }
 
   public synchronized TSStatus extendSchemaTemplate(TemplateExtendInfo templateExtendInfo) {
@@ -824,7 +1007,14 @@ public class ClusterSchemaManager {
 
     ExtendSchemaTemplatePlan extendSchemaTemplatePlan =
         new ExtendSchemaTemplatePlan(templateExtendInfo);
-    TSStatus status = getConsensusManager().write(extendSchemaTemplatePlan).getStatus();
+    TSStatus status;
+    try {
+      status = getConsensusManager().write(extendSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      status = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      status.setMessage(e.getMessage());
+    }
     if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       return status;
     }
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/ConfigNodeProcedureEnv.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/ConfigNodeProcedureEnv.java
index 26a94750e62..7111595c927 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/ConfigNodeProcedureEnv.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/ConfigNodeProcedureEnv.java
@@ -58,6 +58,7 @@ import org.apache.iotdb.confignode.procedure.scheduler.LockQueue;
 import org.apache.iotdb.confignode.procedure.scheduler.ProcedureScheduler;
 import org.apache.iotdb.confignode.rpc.thrift.TAddConsensusGroupReq;
 import org.apache.iotdb.confignode.rpc.thrift.TNodeVersionInfo;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.mpp.rpc.thrift.TActiveTriggerInstanceReq;
 import org.apache.iotdb.mpp.rpc.thrift.TCreateDataRegionReq;
 import org.apache.iotdb.mpp.rpc.thrift.TCreatePipePluginInstanceReq;
@@ -264,14 +265,19 @@ public class ConfigNodeProcedureEnv {
     try {
       // Execute removePeer
       if (getConsensusManager().removeConfigNodePeer(tConfigNodeLocation)) {
-        tsStatus =
-            getConsensusManager().write(new RemoveConfigNodePlan(tConfigNodeLocation)).getStatus();
+        tsStatus = getConsensusManager().write(new RemoveConfigNodePlan(tConfigNodeLocation));
       } else {
         tsStatus =
             new TSStatus(TSStatusCode.REMOVE_CONFIGNODE_ERROR.getStatusCode())
                 .setMessage(
                     "Remove ConfigNode failed because update ConsensusGroup peer information failed.");
       }
+    } catch (ConsensusException e) {
+      LOG.warn("Failed in the write API executing the consensus layer due to: ", e);
+      tsStatus = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      tsStatus.setMessage(e.getMessage());
+    }
+    try {
       if (tsStatus.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         throw new ProcedureException(tsStatus.getMessage());
       }
@@ -364,7 +370,7 @@ public class ConfigNodeProcedureEnv {
             new TUpdateConfigNodeGroupReq(registeredConfigNodes),
             registeredDataNodes);
 
-    if (registeredDataNodes.size() > 0) {
+    if (!registeredDataNodes.isEmpty()) {
       LOG.info(
           "Begin to broadcast the latest configNodeGroup to DataNodes, ConfigNodeGroups: {}, DataNodes: {}",
           registeredConfigNodes,
@@ -548,7 +554,11 @@ public class ConfigNodeProcedureEnv {
 
   public void persistRegionGroup(CreateRegionGroupsPlan createRegionGroupsPlan) {
     // Persist the allocation result
-    getConsensusManager().write(createRegionGroupsPlan);
+    try {
+      getConsensusManager().write(createRegionGroupsPlan);
+    } catch (ConsensusException e) {
+      LOG.warn("Failed in the write API executing the consensus layer due to: ", e);
+    }
   }
 
   /**
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/DataNodeRemoveHandler.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/DataNodeRemoveHandler.java
index e7cf43a2c63..768ca3be944 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/DataNodeRemoveHandler.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/DataNodeRemoveHandler.java
@@ -38,6 +38,7 @@ import org.apache.iotdb.confignode.manager.ConfigManager;
 import org.apache.iotdb.confignode.manager.partition.PartitionMetrics;
 import org.apache.iotdb.confignode.persistence.node.NodeInfo;
 import org.apache.iotdb.confignode.procedure.scheduler.LockQueue;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.mpp.rpc.thrift.TCreatePeerReq;
 import org.apache.iotdb.mpp.rpc.thrift.TDisableDataNodeReq;
 import org.apache.iotdb.mpp.rpc.thrift.TMaintainPeerReq;
@@ -565,7 +566,11 @@ public class DataNodeRemoveHandler {
   public void removeDataNodePersistence(TDataNodeLocation dataNodeLocation) {
     // Remove consensus record
     List<TDataNodeLocation> removeDataNodes = Collections.singletonList(dataNodeLocation);
-    configManager.getConsensusManager().write(new RemoveDataNodePlan(removeDataNodes));
+    try {
+      configManager.getConsensusManager().write(new RemoveDataNodePlan(removeDataNodes));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+    }
 
     // Adjust maxRegionGroupNum
     configManager.getClusterSchemaManager().adjustMaxRegionGroupNum();
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/cq/CreateCQProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/cq/CreateCQProcedure.java
index 480fca9abbd..dcb30fc438c 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/cq/CreateCQProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/cq/CreateCQProcedure.java
@@ -34,7 +34,7 @@ import org.apache.iotdb.confignode.procedure.impl.node.AbstractNodeProcedure;
 import org.apache.iotdb.confignode.procedure.state.cq.CreateCQState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
 import org.apache.iotdb.confignode.rpc.thrift.TCreateCQReq;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
@@ -65,6 +65,9 @@ public class CreateCQProcedure extends AbstractNodeProcedure<CreateCQState> {
 
   private long firstExecutionTime;
 
+  private static final String CONSENSUS_WRITE_ERROR =
+      "Failed in the write API executing the consensus layer due to: ";
+
   public CreateCQProcedure(ScheduledExecutorService executor) {
     super();
     this.executor = executor;
@@ -119,51 +122,47 @@ public class CreateCQProcedure extends AbstractNodeProcedure<CreateCQState> {
   }
 
   private void addCQ(ConfigNodeProcedureEnv env) {
-    ConsensusWriteResponse response =
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new AddCQPlan(req, md5, firstExecutionTime));
-    TSStatus res = response.getStatus();
-    if (res != null) {
-      if (res.code == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        LOGGER.debug("Finish init CQ {} successfully", req.cqId);
-        setNextState(INACTIVE);
-      } else if (res.code == TSStatusCode.CQ_ALREADY_EXIST.getStatusCode()) {
-        LOGGER.info("Failed to init CQ {} because such cq already exists", req.cqId);
-        setFailure(new ProcedureException(new IoTDBException(res.message, res.code)));
-      } else {
-        LOGGER.warn("Failed to init CQ {} because of unknown reasons {}", req.cqId, res);
-        setFailure(new ProcedureException(new IoTDBException(res.message, res.code)));
-      }
+    TSStatus res;
+    try {
+      res =
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new AddCQPlan(req, md5, firstExecutionTime));
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+    }
+    if (res.code == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      LOGGER.debug("Finish init CQ {} successfully", req.cqId);
+      setNextState(INACTIVE);
+    } else if (res.code == TSStatusCode.CQ_ALREADY_EXIST.getStatusCode()) {
+      LOGGER.info("Failed to init CQ {} because such cq already exists", req.cqId);
+      setFailure(new ProcedureException(new IoTDBException(res.message, res.code)));
     } else {
-      LOGGER.warn(
-          "Failed to init CQ {} because of unexpected exception: ",
-          req.cqId,
-          response.getException());
-      setFailure(new ProcedureException(response.getException()));
+      LOGGER.warn("Failed to init CQ {} because of unknown reasons {}", req.cqId, res);
+      setFailure(new ProcedureException(new IoTDBException(res.message, res.code)));
     }
   }
 
   private void activeCQ(ConfigNodeProcedureEnv env) {
-    ConsensusWriteResponse response =
-        env.getConfigManager().getConsensusManager().write(new ActiveCQPlan(req.cqId, md5));
-    TSStatus res = response.getStatus();
-    if (res != null) {
-      if (res.code == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        LOGGER.debug("Finish Scheduling CQ {} successfully", req.cqId);
-      } else if (res.code == TSStatusCode.NO_SUCH_CQ.getStatusCode()) {
-        LOGGER.warn("Failed to active CQ {} because of no such cq: {}", req.cqId, res.message);
-      } else if (res.code == TSStatusCode.CQ_ALREADY_ACTIVE.getStatusCode()) {
-        LOGGER.warn("Failed to active CQ {} because this cq has already been active", req.cqId);
-      } else {
-        LOGGER.warn(
-            "Failed to active CQ {} successfully because of unknown reasons {}", req.cqId, res);
-      }
+    TSStatus res;
+    try {
+      res = env.getConfigManager().getConsensusManager().write(new ActiveCQPlan(req.cqId, md5));
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+    }
+    if (res.code == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      LOGGER.debug("Finish Scheduling CQ {} successfully", req.cqId);
+    } else if (res.code == TSStatusCode.NO_SUCH_CQ.getStatusCode()) {
+      LOGGER.warn("Failed to active CQ {} because of no such cq: {}", req.cqId, res.message);
+    } else if (res.code == TSStatusCode.CQ_ALREADY_ACTIVE.getStatusCode()) {
+      LOGGER.warn("Failed to active CQ {} because this cq has already been active", req.cqId);
     } else {
       LOGGER.warn(
-          "Failed to active CQ {} successfully because of unexpected exception: ",
-          req.cqId,
-          response.getException());
+          "Failed to active CQ {} successfully because of unknown reasons {}", req.cqId, res);
     }
   }
 
@@ -177,28 +176,26 @@ public class CreateCQProcedure extends AbstractNodeProcedure<CreateCQState> {
         break;
       case INACTIVE:
         LOGGER.info("Start [INACTIVE] rollback of CQ {}", req.cqId);
-        ConsensusWriteResponse response =
-            env.getConfigManager().getConsensusManager().write(new DropCQPlan(req.cqId, md5));
-        TSStatus res = response.getStatus();
-        if (res != null) {
-          if (res.code == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-            LOGGER.info("Finish [INACTIVE] rollback of CQ {} successfully", req.cqId);
-          } else if (res.code == TSStatusCode.NO_SUCH_CQ.getStatusCode()) {
-            LOGGER.warn(
-                "Failed to do [INACTIVE] rollback of CQ {} because of no such cq: {}",
-                req.cqId,
-                res.message);
-          } else {
-            LOGGER.warn(
-                "Failed to do [INACTIVE] rollback of CQ {} because of unknown reasons {}",
-                req.cqId,
-                res);
-          }
+        TSStatus res;
+        try {
+          res = env.getConfigManager().getConsensusManager().write(new DropCQPlan(req.cqId, md5));
+        } catch (ConsensusException e) {
+          LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+          res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+          res.setMessage(e.getMessage());
+        }
+        if (res.code == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+          LOGGER.info("Finish [INACTIVE] rollback of CQ {} successfully", req.cqId);
+        } else if (res.code == TSStatusCode.NO_SUCH_CQ.getStatusCode()) {
+          LOGGER.warn(
+              "Failed to do [INACTIVE] rollback of CQ {} because of no such cq: {}",
+              req.cqId,
+              res.message);
         } else {
           LOGGER.warn(
-              "Failed to do [INACTIVE] rollback of CQ {} because of unexpected exception: ",
+              "Failed to do [INACTIVE] rollback of CQ {} because of unknown reasons {}",
               req.cqId,
-              response.getException());
+              res);
         }
 
         break;
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/model/CreateModelProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/model/CreateModelProcedure.java
index be189bd5ce1..2891fe80049 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/model/CreateModelProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/model/CreateModelProcedure.java
@@ -31,7 +31,7 @@ import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
 import org.apache.iotdb.confignode.procedure.impl.node.AbstractNodeProcedure;
 import org.apache.iotdb.confignode.procedure.state.model.CreateModelState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.protocol.client.MLNodeClient;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
@@ -91,13 +91,13 @@ public class CreateModelProcedure extends AbstractNodeProcedure<CreateModelState
 
           LOGGER.info("Start to add model [{}] in ModelTable on Config Nodes", modelId);
 
-          ConsensusWriteResponse response =
+          TSStatus response =
               configManager.getConsensusManager().write(new CreateModelPlan(modelInformation));
-          if (!response.isSuccessful()) {
+          if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
             throw new ModelManagementException(
                 String.format(
                     "Failed to add model [%s] in ModelTable on Config Nodes: %s",
-                    modelId, response.getErrorMessage()));
+                    modelId, response.getMessage()));
           }
 
           setNextState(CreateModelState.CONFIG_NODE_ACTIVE);
@@ -160,9 +160,13 @@ public class CreateModelProcedure extends AbstractNodeProcedure<CreateModelState
       case VALIDATED:
         LOGGER.info("Start [VALIDATED] rollback of model [{}]", modelInformation.getModelId());
 
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new DropModelPlan(modelInformation.getModelId()));
+        try {
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new DropModelPlan(modelInformation.getModelId()));
+        } catch (ConsensusException e) {
+          LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+        }
         break;
 
       default:
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/model/DropModelProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/model/DropModelProcedure.java
index 23ef71e898e..6c1f92c2d4c 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/model/DropModelProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/model/DropModelProcedure.java
@@ -31,7 +31,6 @@ import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
 import org.apache.iotdb.confignode.procedure.impl.node.AbstractNodeProcedure;
 import org.apache.iotdb.confignode.procedure.state.model.DropModelState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.db.protocol.client.MLNodeClient;
 import org.apache.iotdb.mpp.rpc.thrift.TDeleteModelMetricsReq;
 import org.apache.iotdb.rpc.TSStatusCode;
@@ -131,13 +130,13 @@ public class DropModelProcedure extends AbstractNodeProcedure<DropModelState> {
         case ML_NODE_DROPPED:
           LOGGER.info("Start to drop model [{}] on Config Nodes", modelId);
 
-          ConsensusWriteResponse response =
+          TSStatus response =
               env.getConfigManager().getConsensusManager().write(new DropModelPlan(modelId));
-          if (!response.isSuccessful()) {
+          if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
             throw new ModelManagementException(
                 String.format(
                     "Failed to drop model [%s], fail to drop model on Config Nodes: %s",
-                    modelId, response.getErrorMessage()));
+                    modelId, response.getMessage()));
           }
 
           setNextState(DropModelState.CONFIG_NODE_DROPPED);
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/plugin/CreatePipePluginProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/plugin/CreatePipePluginProcedure.java
index c6d68587493..0fb18d7a9d7 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/plugin/CreatePipePluginProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/plugin/CreatePipePluginProcedure.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.confignode.procedure.impl.pipe.plugin;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.pipe.plugin.meta.PipePluginMeta;
 import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.confignode.consensus.request.write.pipe.plugin.CreatePipePluginPlan;
@@ -35,7 +36,7 @@ import org.apache.iotdb.confignode.procedure.impl.node.RemoveConfigNodeProcedure
 import org.apache.iotdb.confignode.procedure.impl.node.RemoveDataNodeProcedure;
 import org.apache.iotdb.confignode.procedure.state.pipe.plugin.CreatePipePluginState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.pipe.api.exception.PipeException;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
@@ -163,10 +164,16 @@ public class CreatePipePluginProcedure extends AbstractNodeProcedure<CreatePipeP
     final CreatePipePluginPlan createPluginPlan =
         new CreatePipePluginPlan(pipePluginMeta, needToSaveJar ? new Binary(jarFile) : null);
 
-    final ConsensusWriteResponse response =
-        configNodeManager.getConsensusManager().write(createPluginPlan);
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response = configNodeManager.getConsensusManager().write(createPluginPlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
 
     setNextState(CreatePipePluginState.CREATE_ON_DATA_NODES);
@@ -226,9 +233,13 @@ public class CreatePipePluginProcedure extends AbstractNodeProcedure<CreatePipeP
         "CreatePipePluginProcedure: rollbackFromCreateOnConfigNodes({})",
         pipePluginMeta.getPluginName());
 
-    env.getConfigManager()
-        .getConsensusManager()
-        .write(new DropPipePluginPlan(pipePluginMeta.getPluginName()));
+    try {
+      env.getConfigManager()
+          .getConsensusManager()
+          .write(new DropPipePluginPlan(pipePluginMeta.getPluginName()));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+    }
   }
 
   private void rollbackFromCreateOnDataNodes(ConfigNodeProcedureEnv env) throws ProcedureException {
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/plugin/DropPipePluginProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/plugin/DropPipePluginProcedure.java
index 676d127e27c..3c31fb6a558 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/plugin/DropPipePluginProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/plugin/DropPipePluginProcedure.java
@@ -31,6 +31,7 @@ import org.apache.iotdb.confignode.procedure.impl.node.RemoveConfigNodeProcedure
 import org.apache.iotdb.confignode.procedure.impl.node.RemoveDataNodeProcedure;
 import org.apache.iotdb.confignode.procedure.state.pipe.plugin.DropPipePluginState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.pipe.api.exception.PipeException;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
@@ -118,7 +119,11 @@ public class DropPipePluginProcedure extends AbstractNodeProcedure<DropPipePlugi
       return Flow.NO_MORE_STATE;
     }
 
-    env.getConfigManager().getConsensusManager().write(new DropPipePluginPlan(pluginName));
+    try {
+      env.getConfigManager().getConsensusManager().write(new DropPipePluginPlan(pluginName));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+    }
 
     setNextState(DropPipePluginState.DROP_ON_DATA_NODES);
     return Flow.HAS_MORE_STATE;
@@ -141,7 +146,11 @@ public class DropPipePluginProcedure extends AbstractNodeProcedure<DropPipePlugi
   private Flow executeFromDropOnConfigNodes(ConfigNodeProcedureEnv env) {
     LOGGER.info("DropPipePluginProcedure: executeFromDropOnConfigNodes({})", pluginName);
 
-    env.getConfigManager().getConsensusManager().write(new DropPipePluginPlan(pluginName));
+    try {
+      env.getConfigManager().getConsensusManager().write(new DropPipePluginPlan(pluginName));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+    }
 
     setNextState(DropPipePluginState.UNLOCK);
     return Flow.HAS_MORE_STATE;
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/runtime/PipeHandleLeaderChangeProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/runtime/PipeHandleLeaderChangeProcedure.java
index 5d8fcf96e23..60626062808 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/runtime/PipeHandleLeaderChangeProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/runtime/PipeHandleLeaderChangeProcedure.java
@@ -21,13 +21,15 @@ package org.apache.iotdb.confignode.procedure.impl.pipe.runtime;
 
 import org.apache.iotdb.common.rpc.thrift.TConsensusGroupId;
 import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.confignode.consensus.request.write.pipe.runtime.PipeHandleLeaderChangePlan;
 import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
 import org.apache.iotdb.confignode.procedure.impl.pipe.AbstractOperatePipeProcedureV2;
 import org.apache.iotdb.confignode.procedure.impl.pipe.PipeTaskOperation;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.pipe.api.exception.PipeException;
+import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
@@ -91,11 +93,16 @@ public class PipeHandleLeaderChangeProcedure extends AbstractOperatePipeProcedur
 
     final PipeHandleLeaderChangePlan pipeHandleLeaderChangePlan =
         new PipeHandleLeaderChangePlan(newDataRegionGroupIdToLeaderDataRegionIdMap);
-
-    final ConsensusWriteResponse response =
-        env.getConfigManager().getConsensusManager().write(pipeHandleLeaderChangePlan);
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response = env.getConfigManager().getConsensusManager().write(pipeHandleLeaderChangePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
   }
 
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/runtime/PipeHandleMetaChangeProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/runtime/PipeHandleMetaChangeProcedure.java
index 7d12e89b8d8..2e59aa287ca 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/runtime/PipeHandleMetaChangeProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/runtime/PipeHandleMetaChangeProcedure.java
@@ -19,14 +19,16 @@
 
 package org.apache.iotdb.confignode.procedure.impl.pipe.runtime;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.pipe.task.meta.PipeMeta;
 import org.apache.iotdb.confignode.consensus.request.write.pipe.runtime.PipeHandleMetaChangePlan;
 import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
 import org.apache.iotdb.confignode.procedure.impl.pipe.AbstractOperatePipeProcedureV2;
 import org.apache.iotdb.confignode.procedure.impl.pipe.PipeTaskOperation;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.pipe.api.exception.PipeException;
+import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import org.slf4j.Logger;
@@ -89,12 +91,19 @@ public class PipeHandleMetaChangeProcedure extends AbstractOperatePipeProcedureV
       pipeMetaList.add(pipeMeta);
     }
 
-    final ConsensusWriteResponse response =
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new PipeHandleMetaChangePlan(pipeMetaList));
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response =
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new PipeHandleMetaChangePlan(pipeMetaList));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
   }
 
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/CreatePipeProcedureV2.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/CreatePipeProcedureV2.java
index 599637b8282..470483c7ac3 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/CreatePipeProcedureV2.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/CreatePipeProcedureV2.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.confignode.procedure.impl.pipe.task;
 
 import org.apache.iotdb.common.rpc.thrift.TConsensusGroupId;
 import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.consensus.index.impl.MinimumProgressIndex;
 import org.apache.iotdb.commons.pipe.task.meta.PipeRuntimeMeta;
 import org.apache.iotdb.commons.pipe.task.meta.PipeStaticMeta;
@@ -33,9 +34,10 @@ import org.apache.iotdb.confignode.procedure.impl.pipe.AbstractOperatePipeProced
 import org.apache.iotdb.confignode.procedure.impl.pipe.PipeTaskOperation;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
 import org.apache.iotdb.confignode.rpc.thrift.TCreatePipeReq;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.pipe.api.exception.PipeException;
+import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import org.slf4j.Logger;
@@ -127,12 +129,19 @@ public class CreatePipeProcedureV2 extends AbstractOperatePipeProcedureV2 {
         "CreatePipeProcedureV2: executeFromWriteConfigNodeConsensus({})",
         createPipeRequest.getPipeName());
 
-    final ConsensusWriteResponse response =
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new CreatePipePlanV2(pipeStaticMeta, pipeRuntimeMeta));
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response =
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new CreatePipePlanV2(pipeStaticMeta, pipeRuntimeMeta));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
   }
 
@@ -173,12 +182,19 @@ public class CreatePipeProcedureV2 extends AbstractOperatePipeProcedureV2 {
         "CreatePipeProcedureV2: rollbackFromWriteConfigNodeConsensus({})",
         createPipeRequest.getPipeName());
 
-    final ConsensusWriteResponse response =
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new DropPipePlanV2(createPipeRequest.getPipeName()));
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response =
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new DropPipePlanV2(createPipeRequest.getPipeName()));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
   }
 
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/DropPipeProcedureV2.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/DropPipeProcedureV2.java
index ff8cd3e7f3f..3d9e226fbf9 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/DropPipeProcedureV2.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/DropPipeProcedureV2.java
@@ -19,13 +19,15 @@
 
 package org.apache.iotdb.confignode.procedure.impl.pipe.task;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.confignode.consensus.request.write.pipe.task.DropPipePlanV2;
 import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
 import org.apache.iotdb.confignode.procedure.impl.pipe.AbstractOperatePipeProcedureV2;
 import org.apache.iotdb.confignode.procedure.impl.pipe.PipeTaskOperation;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.pipe.api.exception.PipeException;
+import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import org.slf4j.Logger;
@@ -73,10 +75,16 @@ public class DropPipeProcedureV2 extends AbstractOperatePipeProcedureV2 {
       throws PipeException {
     LOGGER.info("DropPipeProcedureV2: executeFromWriteConfigNodeConsensus({})", pipeName);
 
-    final ConsensusWriteResponse response =
-        env.getConfigManager().getConsensusManager().write(new DropPipePlanV2(pipeName));
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response = env.getConfigManager().getConsensusManager().write(new DropPipePlanV2(pipeName));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
   }
 
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/StartPipeProcedureV2.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/StartPipeProcedureV2.java
index 4272def5bc1..d36dce384a2 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/StartPipeProcedureV2.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/StartPipeProcedureV2.java
@@ -19,14 +19,16 @@
 
 package org.apache.iotdb.confignode.procedure.impl.pipe.task;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.pipe.task.meta.PipeStatus;
 import org.apache.iotdb.confignode.consensus.request.write.pipe.task.SetPipeStatusPlanV2;
 import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
 import org.apache.iotdb.confignode.procedure.impl.pipe.AbstractOperatePipeProcedureV2;
 import org.apache.iotdb.confignode.procedure.impl.pipe.PipeTaskOperation;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.pipe.api.exception.PipeException;
+import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import org.slf4j.Logger;
@@ -74,12 +76,19 @@ public class StartPipeProcedureV2 extends AbstractOperatePipeProcedureV2 {
       throws PipeException {
     LOGGER.info("StartPipeProcedureV2: executeFromWriteConfigNodeConsensus({})", pipeName);
 
-    final ConsensusWriteResponse response =
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new SetPipeStatusPlanV2(pipeName, PipeStatus.RUNNING));
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response =
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new SetPipeStatusPlanV2(pipeName, PipeStatus.RUNNING));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
   }
 
@@ -116,12 +125,19 @@ public class StartPipeProcedureV2 extends AbstractOperatePipeProcedureV2 {
   protected void rollbackFromWriteConfigNodeConsensus(ConfigNodeProcedureEnv env) {
     LOGGER.info("StartPipeProcedureV2: rollbackFromWriteConfigNodeConsensus({})", pipeName);
 
-    final ConsensusWriteResponse response =
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new SetPipeStatusPlanV2(pipeName, PipeStatus.STOPPED));
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response =
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new SetPipeStatusPlanV2(pipeName, PipeStatus.STOPPED));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
   }
 
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/StopPipeProcedureV2.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/StopPipeProcedureV2.java
index cf866b1d27d..bce57a92a21 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/StopPipeProcedureV2.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/pipe/task/StopPipeProcedureV2.java
@@ -19,14 +19,16 @@
 
 package org.apache.iotdb.confignode.procedure.impl.pipe.task;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.pipe.task.meta.PipeStatus;
 import org.apache.iotdb.confignode.consensus.request.write.pipe.task.SetPipeStatusPlanV2;
 import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
 import org.apache.iotdb.confignode.procedure.impl.pipe.AbstractOperatePipeProcedureV2;
 import org.apache.iotdb.confignode.procedure.impl.pipe.PipeTaskOperation;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.pipe.api.exception.PipeException;
+import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import org.slf4j.Logger;
@@ -74,12 +76,19 @@ public class StopPipeProcedureV2 extends AbstractOperatePipeProcedureV2 {
       throws PipeException {
     LOGGER.info("StopPipeProcedureV2: executeFromWriteConfigNodeConsensus({})", pipeName);
 
-    final ConsensusWriteResponse response =
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new SetPipeStatusPlanV2(pipeName, PipeStatus.STOPPED));
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response =
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new SetPipeStatusPlanV2(pipeName, PipeStatus.STOPPED));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
   }
 
@@ -112,12 +121,19 @@ public class StopPipeProcedureV2 extends AbstractOperatePipeProcedureV2 {
   protected void rollbackFromWriteConfigNodeConsensus(ConfigNodeProcedureEnv env) {
     LOGGER.info("StopPipeProcedureV2: rollbackFromWriteConfigNodeConsensus({})", pipeName);
 
-    final ConsensusWriteResponse response =
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new SetPipeStatusPlanV2(pipeName, PipeStatus.RUNNING));
-    if (!response.isSuccessful()) {
-      throw new PipeException(response.getErrorMessage());
+    TSStatus response;
+    try {
+      response =
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new SetPipeStatusPlanV2(pipeName, PipeStatus.RUNNING));
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+      response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      response.setMessage(e.getMessage());
+    }
+    if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new PipeException(response.getMessage());
     }
   }
 
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java
index 7ea774cc33c..7fd0a1af2bb 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java
@@ -42,6 +42,7 @@ import org.apache.iotdb.confignode.procedure.impl.statemachine.StateMachineProce
 import org.apache.iotdb.confignode.procedure.state.schema.DeleteStorageGroupState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
 import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.apache.thrift.TException;
@@ -215,7 +216,7 @@ public class DeleteDatabaseProcedure
                 new ProcedureException("[DeleteDatabaseProcedure] Delete DatabaseSchema failed"));
           }
       }
-    } catch (TException | IOException e) {
+    } catch (ConsensusException | TException | IOException e) {
       if (isRollbackSupported(state)) {
         setFailure(
             new ProcedureException("[DeleteDatabaseProcedure] Delete Database failed " + state));
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/SetTemplateProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/SetTemplateProcedure.java
index 78e04c750d6..cfde4ed63a5 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/SetTemplateProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/SetTemplateProcedure.java
@@ -43,6 +43,7 @@ import org.apache.iotdb.confignode.procedure.exception.ProcedureYieldException;
 import org.apache.iotdb.confignode.procedure.impl.statemachine.StateMachineProcedure;
 import org.apache.iotdb.confignode.procedure.state.schema.SetTemplateState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.exception.metadata.template.TemplateIncompatibleException;
 import org.apache.iotdb.db.exception.metadata.template.UndefinedTemplateException;
 import org.apache.iotdb.db.schemaengine.template.Template;
@@ -78,6 +79,9 @@ public class SetTemplateProcedure
   private String templateName;
   private String templateSetPath;
 
+  private static final String CONSENSUS_WRITE_ERROR =
+      "Failed in the write API executing the consensus layer due to: ";
+
   public SetTemplateProcedure() {
     super();
   }
@@ -148,12 +152,18 @@ public class SetTemplateProcedure
     // check whether the template can be set on given path
     CheckTemplateSettablePlan checkTemplateSettablePlan =
         new CheckTemplateSettablePlan(templateName, templateSetPath);
-    TemplateInfoResp resp =
-        (TemplateInfoResp)
-            env.getConfigManager()
-                .getConsensusManager()
-                .read(checkTemplateSettablePlan)
-                .getDataset();
+    TemplateInfoResp resp;
+    try {
+      resp =
+          (TemplateInfoResp)
+              env.getConfigManager().getConsensusManager().read(checkTemplateSettablePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      resp = new TemplateInfoResp();
+      resp.setStatus(res);
+    }
     if (resp.getStatus().getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       setNextState(SetTemplateState.PRE_SET);
     } else {
@@ -166,8 +176,14 @@ public class SetTemplateProcedure
   private void preSetTemplate(ConfigNodeProcedureEnv env) {
     PreSetSchemaTemplatePlan preSetSchemaTemplatePlan =
         new PreSetSchemaTemplatePlan(templateName, templateSetPath);
-    TSStatus status =
-        env.getConfigManager().getConsensusManager().write(preSetSchemaTemplatePlan).getStatus();
+    TSStatus status;
+    try {
+      status = env.getConfigManager().getConsensusManager().write(preSetSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      status = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      status.setMessage(e.getMessage());
+    }
     if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       setNextState(SetTemplateState.PRE_RELEASE);
     } else {
@@ -214,9 +230,18 @@ public class SetTemplateProcedure
 
   private Template getTemplate(ConfigNodeProcedureEnv env) {
     GetSchemaTemplatePlan getSchemaTemplatePlan = new GetSchemaTemplatePlan(templateName);
-    TemplateInfoResp templateResp =
-        (TemplateInfoResp)
-            env.getConfigManager().getConsensusManager().read(getSchemaTemplatePlan).getDataset();
+    TemplateInfoResp templateResp;
+    try {
+      templateResp =
+          (TemplateInfoResp)
+              env.getConfigManager().getConsensusManager().read(getSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn("Failed in the read API executing the consensus layer due to: ", e);
+      TSStatus res = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      res.setMessage(e.getMessage());
+      templateResp = new TemplateInfoResp();
+      templateResp.setStatus(res);
+    }
     if (templateResp.getStatus().getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       setFailure(
           new ProcedureException(
@@ -317,8 +342,14 @@ public class SetTemplateProcedure
   private void commitSetTemplate(ConfigNodeProcedureEnv env) {
     CommitSetSchemaTemplatePlan commitSetSchemaTemplatePlan =
         new CommitSetSchemaTemplatePlan(templateName, templateSetPath);
-    TSStatus status =
-        env.getConfigManager().getConsensusManager().write(commitSetSchemaTemplatePlan).getStatus();
+    TSStatus status = null;
+    try {
+      status = env.getConfigManager().getConsensusManager().write(commitSetSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      status = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      status.setMessage(e.getMessage());
+    }
     if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       setNextState(SetTemplateState.COMMIT_RELEASE);
     } else {
@@ -414,8 +445,14 @@ public class SetTemplateProcedure
   private void rollbackPreSet(ConfigNodeProcedureEnv env) {
     PreSetSchemaTemplatePlan preSetSchemaTemplatePlan =
         new PreSetSchemaTemplatePlan(templateName, templateSetPath, true);
-    TSStatus status =
-        env.getConfigManager().getConsensusManager().write(preSetSchemaTemplatePlan).getStatus();
+    TSStatus status = null;
+    try {
+      status = env.getConfigManager().getConsensusManager().write(preSetSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      status = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      status.setMessage(e.getMessage());
+    }
     if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       LOGGER.warn(
           "Failed to rollback pre set template {} on path {} due to {}",
@@ -465,8 +502,14 @@ public class SetTemplateProcedure
   private void rollbackCommitSet(ConfigNodeProcedureEnv env) {
     CommitSetSchemaTemplatePlan commitSetSchemaTemplatePlan =
         new CommitSetSchemaTemplatePlan(templateName, templateSetPath, true);
-    TSStatus status =
-        env.getConfigManager().getConsensusManager().write(commitSetSchemaTemplatePlan).getStatus();
+    TSStatus status = null;
+    try {
+      status = env.getConfigManager().getConsensusManager().write(commitSetSchemaTemplatePlan);
+    } catch (ConsensusException e) {
+      LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+      status = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+      status.setMessage(e.getMessage());
+    }
     if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       LOGGER.warn(
           "Failed to rollback commit set template {} on path {} due to {}",
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/statemachine/CreateRegionGroupsProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/statemachine/CreateRegionGroupsProcedure.java
index 2dab4c451aa..9a017a43eba 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/statemachine/CreateRegionGroupsProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/statemachine/CreateRegionGroupsProcedure.java
@@ -33,6 +33,7 @@ import org.apache.iotdb.confignode.persistence.partition.maintainer.RegionDelete
 import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
 import org.apache.iotdb.confignode.procedure.state.CreateRegionGroupsState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -161,7 +162,11 @@ public class CreateRegionGroupsProcedure
                         }));
 
         env.persistRegionGroup(persistPlan);
-        env.getConfigManager().getConsensusManager().write(offerPlan);
+        try {
+          env.getConfigManager().getConsensusManager().write(offerPlan);
+        } catch (ConsensusException e) {
+          LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+        }
         setNextState(CreateRegionGroupsState.ACTIVATE_REGION_GROUPS);
         break;
       case ACTIVATE_REGION_GROUPS:
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/trigger/CreateTriggerProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/trigger/CreateTriggerProcedure.java
index f6ed578c3ca..71074d28cf7 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/trigger/CreateTriggerProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/trigger/CreateTriggerProcedure.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.confignode.procedure.impl.trigger;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.trigger.TriggerInformation;
 import org.apache.iotdb.commons.trigger.exception.TriggerManagementException;
 import org.apache.iotdb.confignode.consensus.request.write.trigger.AddTriggerInTablePlan;
@@ -32,7 +33,7 @@ import org.apache.iotdb.confignode.procedure.impl.node.AbstractNodeProcedure;
 import org.apache.iotdb.confignode.procedure.state.CreateTriggerState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
 import org.apache.iotdb.confignode.rpc.thrift.TTriggerState;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.Binary;
@@ -90,12 +91,15 @@ public class CreateTriggerProcedure extends AbstractNodeProcedure<CreateTriggerS
               triggerInformation.getTriggerName(),
               jarFile != null);
 
-          ConsensusWriteResponse response =
+          TSStatus response;
+
+          response =
               configManager
                   .getConsensusManager()
                   .write(new AddTriggerInTablePlan(triggerInformation, jarFile));
-          if (!response.isSuccessful()) {
-            throw new TriggerManagementException(response.getErrorMessage());
+
+          if (response.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+            throw new TriggerManagementException(response.getMessage());
           }
 
           setNextState(CreateTriggerState.CONFIG_NODE_INACTIVE);
@@ -189,9 +193,13 @@ public class CreateTriggerProcedure extends AbstractNodeProcedure<CreateTriggerS
       case VALIDATED:
         LOG.info("Start [VALIDATED] rollback of trigger [{}]", triggerInformation.getTriggerName());
 
-        env.getConfigManager()
-            .getConsensusManager()
-            .write(new DeleteTriggerInTablePlan(triggerInformation.getTriggerName()));
+        try {
+          env.getConfigManager()
+              .getConsensusManager()
+              .write(new DeleteTriggerInTablePlan(triggerInformation.getTriggerName()));
+        } catch (ConsensusException e) {
+          LOG.warn("Failed in the write API executing the consensus layer due to: ", e);
+        }
         break;
 
       case CONFIG_NODE_INACTIVE:
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ConfigProcedureStore.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ConfigProcedureStore.java
index 0d209a5f9e1..e2154903ae0 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ConfigProcedureStore.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ConfigProcedureStore.java
@@ -26,6 +26,7 @@ import org.apache.iotdb.confignode.manager.ConfigManager;
 import org.apache.iotdb.confignode.manager.consensus.ConsensusManager;
 import org.apache.iotdb.confignode.persistence.ProcedureInfo;
 import org.apache.iotdb.confignode.procedure.Procedure;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -80,7 +81,11 @@ public class ConfigProcedureStore implements IProcedureStore {
     if (procedureType != null) {
       updateProcedurePlan.setProcedure(procedure);
     }
-    getConsensusManager().write(updateProcedurePlan);
+    try {
+      getConsensusManager().write(updateProcedurePlan);
+    } catch (ConsensusException e) {
+      LOG.warn("Failed in the write API executing the consensus layer due to: ", e);
+    }
   }
 
   @Override
@@ -94,7 +99,11 @@ public class ConfigProcedureStore implements IProcedureStore {
   public void delete(long procId) {
     DeleteProcedurePlan deleteProcedurePlan = new DeleteProcedurePlan();
     deleteProcedurePlan.setProcId(procId);
-    getConsensusManager().write(deleteProcedurePlan);
+    try {
+      getConsensusManager().write(deleteProcedurePlan);
+    } catch (ConsensusException e) {
+      LOG.warn("Failed in the write API executing the consensus layer due to: ", e);
+    }
   }
 
   @Override
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
index 8465fdc6c80..0993272f8a6 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
@@ -162,7 +162,7 @@ import org.apache.iotdb.confignode.rpc.thrift.TUnsetSchemaTemplateReq;
 import org.apache.iotdb.confignode.rpc.thrift.TUpdateModelInfoReq;
 import org.apache.iotdb.confignode.rpc.thrift.TUpdateModelStateReq;
 import org.apache.iotdb.confignode.service.ConfigNode;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.queryengine.plan.statement.AuthorType;
 import org.apache.iotdb.rpc.RpcUtils;
@@ -624,9 +624,9 @@ public class ConfigNodeRPCServiceProcessor implements IConfigNodeRPCService.Ifac
     }
 
     ConsensusGroupId groupId = configManager.getConsensusManager().getConsensusGroupId();
-    ConsensusGenericResponse resp =
-        configManager.getConsensusManager().getConsensusImpl().deletePeer(groupId);
-    if (!resp.isSuccess()) {
+    try {
+      configManager.getConsensusManager().getConsensusImpl().deleteLocalPeer(groupId);
+    } catch (ConsensusException e) {
       return new TSStatus(TSStatusCode.REMOVE_CONFIGNODE_ERROR.getStatusCode())
           .setMessage(
               "remove ConsensusGroup failed because internal failure. See other logs for more details");
diff --git a/iotdb-core/consensus/pom.xml b/iotdb-core/consensus/pom.xml
index 58d252f5a7b..7ca0e29a6cb 100644
--- a/iotdb-core/consensus/pom.xml
+++ b/iotdb-core/consensus/pom.xml
@@ -62,7 +62,7 @@
         </dependency>
         <dependency>
             <groupId>org.apache.iotdb</groupId>
-            <artifactId>thrift-iot-consensus</artifactId>
+            <artifactId>iotdb-thrift-consensus</artifactId>
             <version>${project.version}</version>
         </dependency>
     </dependencies>
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 8a101e721e5..4ee908a7af8 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
@@ -19,137 +19,179 @@
 
 package org.apache.iotdb.consensus;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.consensus.ConsensusGroupId;
+import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.common.request.IConsensusRequest;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.consensus.exception.ConsensusException;
+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.exception.PeerAlreadyInConsensusGroupException;
+import org.apache.iotdb.consensus.exception.PeerNotInConsensusGroupException;
 
 import javax.annotation.concurrent.ThreadSafe;
 
 import java.io.IOException;
 import java.util.List;
 
-/** Consensus module base class. */
+/** Consensus module base interface. */
 @ThreadSafe
 public interface IConsensus {
 
+  /**
+   * Start the consensus module.
+   *
+   * @throws IOException when start consensus errors
+   */
   void start() throws IOException;
 
+  /**
+   * Stop the consensus module.
+   *
+   * @throws IOException when stop consensus errors
+   */
   void stop() throws IOException;
 
-  // write API
-  ConsensusWriteResponse write(ConsensusGroupId groupId, IConsensusRequest request);
+  /**
+   * Write data to the corresponding consensus group.
+   *
+   * @param groupId the consensus group this request belongs
+   * @param request write request
+   * @return write result
+   * @throws ConsensusGroupNotExistException when the specified consensus group doesn't exist
+   * @throws ConsensusException when write doesn't success with other reasons
+   */
+  TSStatus write(ConsensusGroupId groupId, IConsensusRequest request) throws ConsensusException;
 
-  // read API
-  ConsensusReadResponse read(ConsensusGroupId groupId, IConsensusRequest request);
+  /**
+   * Read data from the corresponding consensus group.
+   *
+   * @param groupId the consensus group this request belongs
+   * @param request read request
+   * @return read result
+   * @throws ConsensusGroupNotExistException when the specified consensus group doesn't exist
+   * @throws ConsensusException when read doesn't success with other reasons
+   */
+  DataSet read(ConsensusGroupId groupId, IConsensusRequest request) throws ConsensusException;
 
   // multi consensus group API
 
   /**
    * Require the <em>local node</em> to create a Peer and become a member of the given consensus
    * group. This node will prepare and initialize local statemachine {@link IStateMachine} and other
-   * data structures. After this method returns, we can call {@link #addPeer(ConsensusGroupId,
+   * data structures. After this method returns, we can call {@link #addRemotePeer(ConsensusGroupId,
    * Peer)} to notify original group that this new Peer is prepared to be added into the latest
-   * configuration. createPeer should be called on a node that does not contain any peer of the
+   * configuration. createLocalPeer should be called on a node that does not contain any peer of the
    * consensus group, to avoid one node having more than one replica.
    *
-   * @param groupId the consensus group this Peer belongs
+   * @param groupId the consensus group this peer belongs
    * @param peers other known peers in this group
+   * @throws ConsensusGroupAlreadyExistException when the specified consensus group already exists
+   * @throws IllegalPeerNumException when the peer num is illegal. The exception is that it is legal
+   *     to pass an empty list for RaftConsensus
+   * @throws IllegalPeerEndpointException when peers don't contain local node. The exception is that
+   *     it is legal to pass an empty list for RaftConsensus
+   * @throws ConsensusException when createLocalPeer doesn't success with other reasons
    */
-  ConsensusGenericResponse createPeer(ConsensusGroupId groupId, List<Peer> peers);
+  void createLocalPeer(ConsensusGroupId groupId, List<Peer> peers) throws ConsensusException;
 
   /**
    * When the <em>local node</em> is no longer a member of the given consensus group, call this
    * method to do cleanup works. This method will close local statemachine {@link IStateMachine},
-   * delete local data and do other cleanup works. Be sure this method is called after successfully
-   * removing this peer from current consensus group configuration (by calling {@link
-   * #removePeer(ConsensusGroupId, Peer)} or {@link #changePeer(ConsensusGroupId, List)}).
+   * delete local data and do other cleanup works. deleteLocalPeer should be called after
+   * successfully removing this peer from current consensus group configuration (by calling {@link
+   * #removeRemotePeer(ConsensusGroupId, Peer)}).
    *
-   * @param groupId the consensus group this Peer used to belong
+   * @param groupId the consensus group this peer used to belong
+   * @throws ConsensusGroupNotExistException when the specified consensus group doesn't exist
+   * @throws ConsensusException when deleteLocalPeer doesn't success with other reasons
    */
-  ConsensusGenericResponse deletePeer(ConsensusGroupId groupId);
+  void deleteLocalPeer(ConsensusGroupId groupId) throws ConsensusException;
 
   // single consensus group API
 
   /**
    * Tell the group that a new Peer is prepared to be added into this group. Call {@link
-   * #createPeer(ConsensusGroupId, List)} on the new Peer before calling this method. When this
+   * #createLocalPeer(ConsensusGroupId, List)} on the new Peer before calling this method. When this
    * method returns, the group data should be already transmitted to the new Peer. That is, the new
    * peer is available to answer client requests by the time this method successfully returns.
-   * addPeer should be called on a living peer of the consensus group. For example: We'd like to add
-   * a peer D to (A, B, C) group. We need to execute addPeer in A, B or C.
+   * addRemotePeer should be called on a living peer of the consensus group. For example: We'd like
+   * to add a peer D to (A, B, C) group. We need to execute addPeer in A, B or C.
    *
    * @param groupId the consensus group this peer belongs
    * @param peer the newly added peer
+   * @throws PeerAlreadyInConsensusGroupException when the peer has been added into this consensus
+   *     group
+   * @throws ConsensusException when addRemotePeer doesn't success with other reasons
    */
-  ConsensusGenericResponse addPeer(ConsensusGroupId groupId, Peer peer);
+  void addRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException;
 
   /**
    * Tell the group to remove an active Peer. The removed peer can no longer answer group requests
-   * when this method successfully returns. Call {@link #deletePeer(ConsensusGroupId)} on the
-   * removed Peer to do cleanup jobs after this method successfully returns. removePeer should be
-   * called on a living peer of its consensus group. For example: a group has A, B, C. We'd like to
-   * remove C, in case C is dead, the removePeer should be sent to A or B.
+   * when this method successfully returns. Call {@link #deleteLocalPeer(ConsensusGroupId)} on the
+   * removed Peer to do cleanup jobs after this method successfully returns. removeRemotePeer should
+   * be called on a living peer of its consensus group. For example: a group has A, B, C. We'd like
+   * to remove C, in case C is dead, the removePeer should be sent to A or B.
    *
    * @param groupId the consensus group this peer belongs
    * @param peer the peer to be removed
+   * @throws PeerNotInConsensusGroupException when the peer hasn't yet joined this consensus group
+   * @throws ConsensusException when removeRemotePeer doesn't success with other reasons
    */
-  ConsensusGenericResponse removePeer(ConsensusGroupId groupId, Peer peer);
+  void removeRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException;
+
+  // management API
 
   /**
-   * Tell the group to update an active Peer. The modifiable part of {@link Peer} is TEndPoint.
+   * Transfer the leadership to other peer to meet some load balancing needs.
    *
-   * @param groupId the consensus group this peer belongs
-   * @param oldPeer the peer to be updated
-   * @param newPeer the peer to be updated to
+   * @param groupId the consensus group which should execute this command
+   * @param newLeader the target leader peer
+   * @throws ConsensusGroupNotExistException when the specified consensus group doesn't exist
+   * @throws ConsensusException when transferLeader doesn't success with other reasons
    */
-  // TODO: @SzyWilliam @SpriCoder Please implement this method
-  ConsensusGenericResponse updatePeer(ConsensusGroupId groupId, Peer oldPeer, Peer newPeer);
+  void transferLeader(ConsensusGroupId groupId, Peer newLeader) throws ConsensusException;
 
   /**
-   * Change group configuration. This method allows you to add/remove multiple Peers at once. This
-   * method is similar to {@link #addPeer(ConsensusGroupId, Peer)} or {@link
-   * #removePeer(ConsensusGroupId, Peer)}
+   * Trigger the snapshot of the corresponding consensus group.
    *
-   * @param groupId the consensus group
-   * @param newPeers the new member configuration of this group
+   * @param groupId the consensus group which should execute this command
+   * @throws ConsensusException when triggerSnapshot doesn't success with other reasons
    */
-  ConsensusGenericResponse changePeer(ConsensusGroupId groupId, List<Peer> newPeers);
+  void triggerSnapshot(ConsensusGroupId groupId) throws ConsensusException;
 
   /**
-   * Tell the group to [create a new Peer on new node] and [add this member to join the group].
-   *
-   * <p>The underlying implementation should <br>
-   * 1. first call createPeer on the new member <br>
-   * 2. then call addPeer for configuration change <br>
-   * Call this method on any node of the <em>original group</em>. <br>
-   * NOTICE: Currently only RatisConsensus implements this method.
+   * Determine if the current peer is the leader in the corresponding consensus group.
    *
    * @param groupId the consensus group
-   * @param newNode the new member
-   * @param originalGroup the original members of the existed group
+   * @return true or false
    */
-  default ConsensusGenericResponse addNewNodeToExistedGroup(
-      ConsensusGroupId groupId, Peer newNode, List<Peer> originalGroup) {
-    return ConsensusGenericResponse.newBuilder()
-        .setSuccess(false)
-        .setException(
-            new ConsensusException(
-                "addNewNodeToExistedGroup method is not implemented by " + this + " class"))
-        .build();
-  }
-
-  // management API
-  ConsensusGenericResponse transferLeader(ConsensusGroupId groupId, Peer newLeader);
-
-  ConsensusGenericResponse triggerSnapshot(ConsensusGroupId groupId);
-
   boolean isLeader(ConsensusGroupId groupId);
 
+  /**
+   * Determine if the current peer is the leader and already able to provide services in the
+   * corresponding consensus group.
+   *
+   * @param groupId the consensus group
+   * @return true or false
+   */
+  boolean isLeaderReady(ConsensusGroupId groupId);
+
+  /**
+   * Return the leader peer of the corresponding consensus group.
+   *
+   * @param groupId the consensus group
+   * @return return null if group doesn't exist or leader is undetermined, or return leader Peer
+   */
   Peer getLeader(ConsensusGroupId groupId);
 
+  /**
+   * Return all consensus group ids.
+   *
+   * @return consensusGroupId list
+   */
   List<ConsensusGroupId> getAllConsensusGroupIds();
 }
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/ConsensusGroup.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/ConsensusGroup.java
index 42679cc5153..83719753c66 100644
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/ConsensusGroup.java
+++ b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/ConsensusGroup.java
@@ -24,7 +24,6 @@ import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import java.util.List;
 import java.util.Objects;
 
-// TODO Use a mature IDL framework such as Protobuf to manage this structure
 public class ConsensusGroup {
 
   private final ConsensusGroupId groupId;
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/Peer.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/Peer.java
index 391693f1197..11ad7b5bf51 100644
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/Peer.java
+++ b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/Peer.java
@@ -32,7 +32,6 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.Objects;
 
-// TODO Use a mature IDL framework such as Protobuf to manage this structure
 public class Peer {
 
   private final Logger logger = LoggerFactory.getLogger(Peer.class);
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/Utils.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/Utils.java
index 96d381949e3..82d7ea43a1b 100644
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/Utils.java
+++ b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/Utils.java
@@ -35,6 +35,8 @@ import java.util.List;
 public class Utils {
   private static final Logger logger = LoggerFactory.getLogger(Utils.class);
 
+  private Utils() {}
+
   public static List<Path> listAllRegularFilesRecursively(File rootDir) {
     List<Path> allFiles = new ArrayList<>();
     try {
@@ -42,14 +44,12 @@ public class Utils {
           rootDir.toPath(),
           new FileVisitor<Path>() {
             @Override
-            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
-                throws IOException {
+            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
               return FileVisitResult.CONTINUE;
             }
 
             @Override
-            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
-                throws IOException {
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
               if (attrs.isRegularFile()) {
                 allFiles.add(file);
               }
@@ -57,14 +57,13 @@ public class Utils {
             }
 
             @Override
-            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+            public FileVisitResult visitFileFailed(Path file, IOException exc) {
               logger.info("visit file {} failed due to {}", file.toAbsolutePath(), exc);
               return FileVisitResult.TERMINATE;
             }
 
             @Override
-            public FileVisitResult postVisitDirectory(Path dir, IOException exc)
-                throws IOException {
+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
               return FileVisitResult.CONTINUE;
             }
           });
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/request/ByteBufferConsensusRequest.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/request/ByteBufferConsensusRequest.java
index 0310a4e3d30..6ce31cc1859 100644
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/request/ByteBufferConsensusRequest.java
+++ b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/request/ByteBufferConsensusRequest.java
@@ -21,12 +21,12 @@ package org.apache.iotdb.consensus.common.request;
 
 import java.nio.ByteBuffer;
 
-/*
-In general, for the requests from the leader, we can directly strong-cast the class to reduce
-the cost of deserialization during the execution of the leader state machine. For the requests
-received by the followers, the responsibility of deserialization can generally be transferred
-to the state machine layer
-*/
+/**
+ * In general, for the requests from the leader, we can directly strong-cast the class to reduce the
+ * cost of deserialization during the execution of the leader state machine. For the requests
+ * received by the followers, the responsibility of deserialization can generally be transferred to
+ * the state machine layer
+ */
 public class ByteBufferConsensusRequest implements IConsensusRequest {
 
   private final ByteBuffer byteBuffer;
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusGenericResponse.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusGenericResponse.java
deleted file mode 100644
index acf67f23393..00000000000
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusGenericResponse.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.consensus.common.response;
-
-import org.apache.iotdb.consensus.exception.ConsensusException;
-
-public class ConsensusGenericResponse extends ConsensusResponse {
-
-  private final boolean success;
-
-  public ConsensusGenericResponse(ConsensusException exception, boolean success) {
-    super(exception);
-    this.success = success;
-  }
-
-  public boolean isSuccess() {
-    return success;
-  }
-
-  @Override
-  public String toString() {
-    return "ConsensusGenericResponse{" + "success=" + success + "} " + super.toString();
-  }
-
-  public static ConsensusGenericResponse.Builder newBuilder() {
-    return new ConsensusGenericResponse.Builder();
-  }
-
-  public static class Builder {
-    private boolean success;
-    private ConsensusException exception;
-
-    public ConsensusGenericResponse build() {
-      return new ConsensusGenericResponse(exception, success);
-    }
-
-    public ConsensusGenericResponse.Builder setException(ConsensusException exception) {
-      this.exception = exception;
-      return this;
-    }
-
-    public ConsensusGenericResponse.Builder setSuccess(boolean success) {
-      this.success = success;
-      return this;
-    }
-  }
-}
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusReadResponse.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusReadResponse.java
deleted file mode 100644
index 7c3a45bd90b..00000000000
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusReadResponse.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.consensus.common.response;
-
-import org.apache.iotdb.consensus.common.DataSet;
-import org.apache.iotdb.consensus.exception.ConsensusException;
-
-public class ConsensusReadResponse extends ConsensusResponse {
-
-  private final DataSet dataset;
-
-  public ConsensusReadResponse(ConsensusException exception, DataSet dataset) {
-    super(exception);
-    this.dataset = dataset;
-  }
-
-  public DataSet getDataset() {
-    return dataset;
-  }
-
-  public boolean isSuccess() {
-    return exception == null;
-  }
-
-  @Override
-  public String toString() {
-    return "ConsensusReadResponse{" + "dataset=" + dataset + ", exception=" + exception + "}";
-  }
-
-  public static ConsensusReadResponse.Builder newBuilder() {
-    return new ConsensusReadResponse.Builder();
-  }
-
-  public static class Builder {
-    private ConsensusException exception;
-    private DataSet dataset;
-
-    public ConsensusReadResponse build() {
-      return new ConsensusReadResponse(exception, dataset);
-    }
-
-    public ConsensusReadResponse.Builder setException(ConsensusException exception) {
-      this.exception = exception;
-      return this;
-    }
-
-    public ConsensusReadResponse.Builder setDataSet(DataSet dataset) {
-      this.dataset = dataset;
-      return this;
-    }
-  }
-}
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusResponse.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusResponse.java
deleted file mode 100644
index 4b4beff769d..00000000000
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusResponse.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.consensus.common.response;
-
-import org.apache.iotdb.consensus.exception.ConsensusException;
-
-public abstract class ConsensusResponse {
-  protected final ConsensusException exception;
-
-  protected ConsensusResponse(ConsensusException exception) {
-    this.exception = exception;
-  }
-
-  public ConsensusException getException() {
-    return exception;
-  }
-
-  @Override
-  public String toString() {
-    return "exception=" + exception;
-  }
-}
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusWriteResponse.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusWriteResponse.java
deleted file mode 100644
index fdb7626c1d5..00000000000
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/common/response/ConsensusWriteResponse.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.consensus.common.response;
-
-import org.apache.iotdb.common.rpc.thrift.TSStatus;
-import org.apache.iotdb.consensus.exception.ConsensusException;
-import org.apache.iotdb.rpc.TSStatusCode;
-
-public class ConsensusWriteResponse extends ConsensusResponse {
-
-  private final TSStatus status;
-
-  public ConsensusWriteResponse(ConsensusException exception, TSStatus status) {
-    super(exception);
-    this.status = status;
-  }
-
-  public TSStatus getStatus() {
-    return status;
-  }
-
-  @Override
-  public String toString() {
-    return "ConsensusWriteResponse{" + "status=" + status + "} " + super.toString();
-  }
-
-  public boolean isSuccessful() {
-    return status != null && status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode();
-  }
-
-  public String getErrorMessage() {
-    if (status != null && status.message != null && status.message.length() > 0) {
-      return status.message;
-    }
-    if (exception != null
-        && exception.getMessage() != null
-        && exception.getMessage().length() > 0) {
-      return exception.getMessage();
-    }
-    return "unknown error message";
-  }
-
-  public static ConsensusWriteResponse.Builder newBuilder() {
-    return new ConsensusWriteResponse.Builder();
-  }
-
-  public static class Builder {
-    private TSStatus status;
-    private ConsensusException exception;
-
-    public ConsensusWriteResponse build() {
-      return new ConsensusWriteResponse(exception, status);
-    }
-
-    public Builder setException(ConsensusException exception) {
-      this.exception = exception;
-      return this;
-    }
-
-    public Builder setStatus(TSStatus status) {
-      this.status = status;
-      return this;
-    }
-  }
-}
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/config/ConsensusConfig.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/config/ConsensusConfig.java
index 5ce00636031..74600440b7b 100644
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/config/ConsensusConfig.java
+++ b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/config/ConsensusConfig.java
@@ -31,7 +31,7 @@ public class ConsensusConfig {
   private final String storageDir;
   private final TConsensusGroupType consensusGroupType;
   private final RatisConfig ratisConfig;
-  private final IoTConsensusConfig ioTConsensusConfig;
+  private final IoTConsensusConfig iotConsensusConfig;
 
   private ConsensusConfig(
       TEndPoint thisNode,
@@ -39,13 +39,13 @@ public class ConsensusConfig {
       String storageDir,
       TConsensusGroupType consensusGroupType,
       RatisConfig ratisConfig,
-      IoTConsensusConfig ioTConsensusConfig) {
+      IoTConsensusConfig iotConsensusConfig) {
     this.thisNodeEndPoint = thisNode;
     this.thisNodeId = thisNodeId;
     this.storageDir = storageDir;
     this.consensusGroupType = consensusGroupType;
     this.ratisConfig = ratisConfig;
-    this.ioTConsensusConfig = ioTConsensusConfig;
+    this.iotConsensusConfig = iotConsensusConfig;
   }
 
   public TEndPoint getThisNodeEndPoint() {
@@ -68,8 +68,8 @@ public class ConsensusConfig {
     return ratisConfig;
   }
 
-  public IoTConsensusConfig getIoTConsensusConfig() {
-    return ioTConsensusConfig;
+  public IoTConsensusConfig getIotConsensusConfig() {
+    return iotConsensusConfig;
   }
 
   public static ConsensusConfig.Builder newBuilder() {
@@ -83,7 +83,7 @@ public class ConsensusConfig {
     private String storageDir;
     private TConsensusGroupType consensusGroupType;
     private RatisConfig ratisConfig;
-    private IoTConsensusConfig ioTConsensusConfig;
+    private IoTConsensusConfig iotConsensusConfig;
 
     public ConsensusConfig build() {
       return new ConsensusConfig(
@@ -92,7 +92,7 @@ public class ConsensusConfig {
           storageDir,
           consensusGroupType,
           Optional.ofNullable(ratisConfig).orElseGet(() -> RatisConfig.newBuilder().build()),
-          Optional.ofNullable(ioTConsensusConfig)
+          Optional.ofNullable(iotConsensusConfig)
               .orElseGet(() -> IoTConsensusConfig.newBuilder().build()));
     }
 
@@ -121,8 +121,8 @@ public class ConsensusConfig {
       return this;
     }
 
-    public Builder setIoTConsensusConfig(IoTConsensusConfig ioTConsensusConfig) {
-      this.ioTConsensusConfig = ioTConsensusConfig;
+    public Builder setIoTConsensusConfig(IoTConsensusConfig iotConsensusConfig) {
+      this.iotConsensusConfig = iotConsensusConfig;
       return this;
     }
   }
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/NodeReadOnlyException.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/NodeReadOnlyException.java
deleted file mode 100644
index 89ff0d854c7..00000000000
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/NodeReadOnlyException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.consensus.exception;
-
-import org.apache.ratis.protocol.RaftPeer;
-
-public class NodeReadOnlyException extends ConsensusException {
-  public NodeReadOnlyException(RaftPeer peer) {
-    super(
-        String.format(
-            "Current Peer %s in Address %s is in Read Only State",
-            peer.getId(), peer.getAddress()));
-  }
-}
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/PeerNotInConsensusGroupException.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/PeerNotInConsensusGroupException.java
index 6247361e0ab..64bc461fa91 100644
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/PeerNotInConsensusGroupException.java
+++ b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/PeerNotInConsensusGroupException.java
@@ -21,10 +21,8 @@ package org.apache.iotdb.consensus.exception;
 
 import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 
-import org.apache.ratis.protocol.RaftPeer;
-
 public class PeerNotInConsensusGroupException extends ConsensusException {
-  public PeerNotInConsensusGroupException(ConsensusGroupId groupId, RaftPeer peer) {
-    super(String.format("Peer %s is not in group %d", peer.getAddress(), groupId.getId()));
+  public PeerNotInConsensusGroupException(ConsensusGroupId groupId, String peer) {
+    super(String.format("Peer %s is not in group %d", peer, groupId.getId()));
   }
 }
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/RatisUnderRecoveryException.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/RatisUnderRecoveryException.java
index 762b7ea432c..edf67629890 100644
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/RatisUnderRecoveryException.java
+++ b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/exception/RatisUnderRecoveryException.java
@@ -24,7 +24,8 @@ public class RatisUnderRecoveryException extends ConsensusException {
 
   public RatisUnderRecoveryException(Throwable cause) {
     super(
-        "Ratis Server is redoing Raft Log and cannot serve read requests now. Please try read later: "
+        "Raft Server is redoing Raft Log and cannot serve read requests now. "
+            + "Please try read later: "
             + cause,
         cause);
   }
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 3afc4590c7b..3da7df08dc1 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
@@ -28,14 +28,13 @@ import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 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.StatusUtils;
 import org.apache.iotdb.consensus.IConsensus;
 import org.apache.iotdb.consensus.IStateMachine;
 import org.apache.iotdb.consensus.IStateMachine.Registry;
+import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.common.request.IConsensusRequest;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
 import org.apache.iotdb.consensus.config.IoTConsensusConfig;
 import org.apache.iotdb.consensus.exception.ConsensusException;
@@ -44,6 +43,8 @@ import org.apache.iotdb.consensus.exception.ConsensusGroupModifyPeerException;
 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.exception.PeerAlreadyInConsensusGroupException;
+import org.apache.iotdb.consensus.exception.PeerNotInConsensusGroupException;
 import org.apache.iotdb.consensus.iot.client.AsyncIoTConsensusServiceClient;
 import org.apache.iotdb.consensus.iot.client.IoTConsensusClientPool.AsyncIoTConsensusServiceClientPoolFactory;
 import org.apache.iotdb.consensus.iot.client.IoTConsensusClientPool.SyncIoTConsensusServiceClientPoolFactory;
@@ -65,6 +66,7 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -91,29 +93,29 @@ public class IoTConsensus implements IConsensus {
     this.thisNode = config.getThisNodeEndPoint();
     this.thisNodeId = config.getThisNodeId();
     this.storageDir = new File(config.getStorageDir());
-    this.config = config.getIoTConsensusConfig();
+    this.config = config.getIotConsensusConfig();
     this.registry = registry;
-    this.service = new IoTConsensusRPCService(thisNode, config.getIoTConsensusConfig());
+    this.service = new IoTConsensusRPCService(thisNode, config.getIotConsensusConfig());
     this.clientManager =
         new IClientManager.Factory<TEndPoint, AsyncIoTConsensusServiceClient>()
             .createClientManager(
-                new AsyncIoTConsensusServiceClientPoolFactory(config.getIoTConsensusConfig()));
+                new AsyncIoTConsensusServiceClientPoolFactory(config.getIotConsensusConfig()));
     this.syncClientManager =
         new IClientManager.Factory<TEndPoint, SyncIoTConsensusServiceClient>()
             .createClientManager(
-                new SyncIoTConsensusServiceClientPoolFactory(config.getIoTConsensusConfig()));
+                new SyncIoTConsensusServiceClientPoolFactory(config.getIotConsensusConfig()));
     this.retryService =
         IoTDBThreadPoolFactory.newSingleThreadScheduledExecutor(
             ThreadName.LOG_DISPATCHER_RETRY_EXECUTOR.getName());
     // init IoTConsensus memory manager
     IoTConsensusMemoryManager.getInstance()
         .init(
-            config.getIoTConsensusConfig().getReplication().getAllocateMemoryForConsensus(),
-            config.getIoTConsensusConfig().getReplication().getAllocateMemoryForQueue());
+            config.getIotConsensusConfig().getReplication().getAllocateMemoryForConsensus(),
+            config.getIotConsensusConfig().getReplication().getAllocateMemoryForQueue());
   }
 
   @Override
-  public void start() throws IOException {
+  public synchronized void start() throws IOException {
     initAndRecover();
     service.initAsyncedServiceImpl(new IoTConsensusRPCServiceProcessor(this));
     try {
@@ -126,7 +128,7 @@ public class IoTConsensus implements IConsensus {
   private void initAndRecover() throws IOException {
     if (!storageDir.exists()) {
       if (!storageDir.mkdirs()) {
-        logger.warn("Unable to create consensus dir at {}", storageDir);
+        throw new IOException(String.format("Unable to create consensus dir at %s", storageDir));
       }
     } else {
       try (DirectoryStream<Path> stream = Files.newDirectoryStream(storageDir.toPath())) {
@@ -153,7 +155,7 @@ public class IoTConsensus implements IConsensus {
   }
 
   @Override
-  public void stop() {
+  public synchronized void stop() {
     stateMachineMap.values().parallelStream().forEach(IoTConsensusServerImpl::stop);
     clientManager.close();
     syncClientManager.close();
@@ -168,85 +170,79 @@ public class IoTConsensus implements IConsensus {
   }
 
   @Override
-  public ConsensusWriteResponse write(ConsensusGroupId groupId, IConsensusRequest request) {
-    IoTConsensusServerImpl impl = stateMachineMap.get(groupId);
-    if (impl == null) {
-      return ConsensusWriteResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
-    }
-
-    TSStatus status;
+  public TSStatus write(ConsensusGroupId groupId, IConsensusRequest request)
+      throws ConsensusException {
+    IoTConsensusServerImpl impl =
+        Optional.ofNullable(stateMachineMap.get(groupId))
+            .orElseThrow(() -> new ConsensusGroupNotExistException(groupId));
     if (impl.isReadOnly()) {
-      status = new TSStatus(TSStatusCode.SYSTEM_READ_ONLY.getStatusCode());
-      status.setMessage("Fail to do non-query operations because system is read-only.");
+      return StatusUtils.getStatus(TSStatusCode.SYSTEM_READ_ONLY);
     } else if (!impl.isActive()) {
-      // TODO: (xingtanzjr) whether we need to define a new status to indicate the inactive status ?
-      status = RpcUtils.getStatus(TSStatusCode.WRITE_PROCESS_REJECT);
-      status.setMessage("peer is inactive and not ready to receive sync log request.");
+      return RpcUtils.getStatus(
+          TSStatusCode.WRITE_PROCESS_REJECT,
+          "peer is inactive and not ready to receive sync log request.");
     } else {
-      status = impl.write(request);
+      return impl.write(request);
     }
-    return ConsensusWriteResponse.newBuilder().setStatus(status).build();
   }
 
   @Override
-  public ConsensusReadResponse read(ConsensusGroupId groupId, IConsensusRequest request) {
-    IoTConsensusServerImpl impl = stateMachineMap.get(groupId);
-    if (impl == null) {
-      return ConsensusReadResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
-    }
-    return ConsensusReadResponse.newBuilder().setDataSet(impl.read(request)).build();
+  public DataSet read(ConsensusGroupId groupId, IConsensusRequest request)
+      throws ConsensusException {
+    return Optional.ofNullable(stateMachineMap.get(groupId))
+        .orElseThrow(() -> new ConsensusGroupNotExistException(groupId))
+        .read(request);
   }
 
+  @SuppressWarnings("java:S2201")
   @Override
-  public ConsensusGenericResponse createPeer(ConsensusGroupId groupId, List<Peer> peers) {
+  public void createLocalPeer(ConsensusGroupId groupId, List<Peer> peers)
+      throws ConsensusException {
     int consensusGroupSize = peers.size();
     if (consensusGroupSize == 0) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new IllegalPeerNumException(consensusGroupSize))
-          .build();
+      throw new IllegalPeerNumException(consensusGroupSize);
     }
     if (!peers.contains(new Peer(groupId, thisNodeId, thisNode))) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new IllegalPeerEndpointException(thisNode, peers))
-          .build();
+      throw new IllegalPeerEndpointException(thisNode, peers);
     }
     AtomicBoolean exist = new AtomicBoolean(true);
-    stateMachineMap.computeIfAbsent(
-        groupId,
-        k -> {
-          exist.set(false);
-          String path = buildPeerDir(storageDir, groupId);
-          File file = new File(path);
-          if (!file.mkdirs()) {
-            logger.warn("Unable to create consensus dir for group {} at {}", groupId, path);
-          }
-          IoTConsensusServerImpl impl =
-              new IoTConsensusServerImpl(
-                  path,
-                  new Peer(groupId, thisNodeId, thisNode),
-                  peers,
-                  registry.apply(groupId),
-                  retryService,
-                  clientManager,
-                  syncClientManager,
-                  config);
-          impl.start();
-          return impl;
-        });
+    Optional.ofNullable(
+            stateMachineMap.computeIfAbsent(
+                groupId,
+                k -> {
+                  exist.set(false);
+
+                  String path = buildPeerDir(storageDir, groupId);
+                  File file = new File(path);
+                  if (!file.mkdirs()) {
+                    logger.warn("Unable to create consensus dir for group {} at {}", groupId, path);
+                    return null;
+                  }
+
+                  IoTConsensusServerImpl impl =
+                      new IoTConsensusServerImpl(
+                          path,
+                          new Peer(groupId, thisNodeId, thisNode),
+                          peers,
+                          registry.apply(groupId),
+                          retryService,
+                          clientManager,
+                          syncClientManager,
+                          config);
+                  impl.start();
+                  return impl;
+                }))
+        .orElseThrow(
+            () ->
+                new ConsensusException(
+                    String.format("Unable to create consensus dir for group %s", groupId)));
     if (exist.get()) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new ConsensusGroupAlreadyExistException(groupId))
-          .build();
+      throw new ConsensusGroupAlreadyExistException(groupId);
     }
-    return ConsensusGenericResponse.newBuilder().setSuccess(true).build();
   }
 
   @Override
-  public ConsensusGenericResponse deletePeer(ConsensusGroupId groupId) {
+  public void deleteLocalPeer(ConsensusGroupId groupId) throws ConsensusException {
     AtomicBoolean exist = new AtomicBoolean(false);
     stateMachineMap.computeIfPresent(
         groupId,
@@ -256,22 +252,18 @@ public class IoTConsensus implements IConsensus {
           FileUtils.deleteDirectory(new File(buildPeerDir(storageDir, groupId)));
           return null;
         });
-
     if (!exist.get()) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
+      throw new ConsensusGroupNotExistException(groupId);
     }
-    return ConsensusGenericResponse.newBuilder().setSuccess(true).build();
   }
 
   @Override
-  public ConsensusGenericResponse addPeer(ConsensusGroupId groupId, Peer peer) {
-    IoTConsensusServerImpl impl = stateMachineMap.get(groupId);
-    if (impl == null) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
+  public void addRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException {
+    IoTConsensusServerImpl impl =
+        Optional.ofNullable(stateMachineMap.get(groupId))
+            .orElseThrow(() -> new ConsensusGroupNotExistException(groupId));
+    if (impl.getConfiguration().contains(peer)) {
+      throw new PeerAlreadyInConsensusGroupException(groupId, peer);
     }
     try {
       // step 1: inactive new Peer to prepare for following steps
@@ -304,14 +296,8 @@ public class IoTConsensus implements IConsensus {
       doSpotClean(peer, impl);
 
     } catch (ConsensusGroupModifyPeerException e) {
-      logger.error("cannot execute addPeer() for {}", peer, e);
-      return ConsensusGenericResponse.newBuilder()
-          .setSuccess(false)
-          .setException(new ConsensusException(e.getMessage()))
-          .build();
+      throw new ConsensusException(e.getMessage());
     }
-
-    return ConsensusGenericResponse.newBuilder().setSuccess(true).build();
   }
 
   private void doSpotClean(Peer peer, IoTConsensusServerImpl impl) {
@@ -323,21 +309,20 @@ public class IoTConsensus implements IConsensus {
   }
 
   @Override
-  public ConsensusGenericResponse removePeer(ConsensusGroupId groupId, Peer peer) {
-    IoTConsensusServerImpl impl = stateMachineMap.get(groupId);
-    if (impl == null) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
+  public void removeRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException {
+    IoTConsensusServerImpl impl =
+        Optional.ofNullable(stateMachineMap.get(groupId))
+            .orElseThrow(() -> new ConsensusGroupNotExistException(groupId));
+
+    if (!impl.getConfiguration().contains(peer)) {
+      throw new PeerNotInConsensusGroupException(groupId, peer.toString());
     }
+
     try {
       // let other peers remove the sync channel with target peer
       impl.notifyPeersToRemoveSyncLogChannel(peer);
     } catch (ConsensusGroupModifyPeerException e) {
-      return ConsensusGenericResponse.newBuilder()
-          .setSuccess(false)
-          .setException(new ConsensusException(e.getMessage()))
-          .build();
+      throw new ConsensusException(e.getMessage());
     }
 
     try {
@@ -346,45 +331,25 @@ public class IoTConsensus implements IConsensus {
       // wait its SyncLog to complete
       impl.waitTargetPeerUntilSyncLogCompleted(peer);
     } catch (ConsensusGroupModifyPeerException e) {
-      // we only log warning here because sometimes the target peer may already be down
-      logger.warn("cannot wait {} to complete SyncLog. error message: {}", peer, e.getMessage());
+      throw new ConsensusException(e.getMessage());
     }
-
-    return ConsensusGenericResponse.newBuilder().setSuccess(true).build();
   }
 
   @Override
-  public ConsensusGenericResponse updatePeer(ConsensusGroupId groupId, Peer oldPeer, Peer newPeer) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(true).build();
+  public void transferLeader(ConsensusGroupId groupId, Peer newLeader) throws ConsensusException {
+    throw new ConsensusException("IoTConsensus does not support leader transfer");
   }
 
   @Override
-  public ConsensusGenericResponse changePeer(ConsensusGroupId groupId, List<Peer> newPeers) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(false).build();
-  }
-
-  @Override
-  public ConsensusGenericResponse transferLeader(ConsensusGroupId groupId, Peer newLeader) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(true).build();
-  }
-
-  @Override
-  public ConsensusGenericResponse triggerSnapshot(ConsensusGroupId groupId) {
-    IoTConsensusServerImpl impl = stateMachineMap.get(groupId);
-    if (impl == null) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
-    }
+  public void triggerSnapshot(ConsensusGroupId groupId) throws ConsensusException {
+    IoTConsensusServerImpl impl =
+        Optional.ofNullable(stateMachineMap.get(groupId))
+            .orElseThrow(() -> new ConsensusGroupNotExistException(groupId));
     try {
       impl.takeSnapshot();
     } catch (ConsensusGroupModifyPeerException e) {
-      return ConsensusGenericResponse.newBuilder()
-          .setSuccess(false)
-          .setException(new ConsensusException(e.getMessage()))
-          .build();
+      throw new ConsensusException(e.getMessage());
     }
-    return ConsensusGenericResponse.newBuilder().setSuccess(true).build();
   }
 
   @Override
@@ -392,6 +357,11 @@ public class IoTConsensus implements IConsensus {
     return true;
   }
 
+  @Override
+  public boolean isLeaderReady(ConsensusGroupId groupId) {
+    return true;
+  }
+
   @Override
   public Peer getLeader(ConsensusGroupId groupId) {
     if (!stateMachineMap.containsKey(groupId)) {
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 d73964c7002..0bc95247d69 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
@@ -33,21 +33,18 @@ import org.apache.iotdb.commons.concurrent.ThreadName;
 import org.apache.iotdb.commons.concurrent.threadpool.ScheduledExecutorUtil;
 import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import org.apache.iotdb.commons.service.metric.MetricService;
+import org.apache.iotdb.commons.utils.StatusUtils;
 import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.consensus.IConsensus;
 import org.apache.iotdb.consensus.IStateMachine;
 import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.common.request.IConsensusRequest;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
 import org.apache.iotdb.consensus.config.RatisConfig;
 import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupNotExistException;
-import org.apache.iotdb.consensus.exception.NodeReadOnlyException;
 import org.apache.iotdb.consensus.exception.PeerAlreadyInConsensusGroupException;
 import org.apache.iotdb.consensus.exception.PeerNotInConsensusGroupException;
 import org.apache.iotdb.consensus.exception.RatisRequestFailedException;
@@ -56,6 +53,7 @@ import org.apache.iotdb.consensus.ratis.metrics.RatisMetricSet;
 import org.apache.iotdb.consensus.ratis.metrics.RatisMetricsManager;
 import org.apache.iotdb.consensus.ratis.utils.RatisLogMonitor;
 import org.apache.iotdb.consensus.ratis.utils.Utils;
+import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.apache.commons.pool2.KeyedObjectPool;
 import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
@@ -78,6 +76,8 @@ import org.apache.ratis.protocol.exceptions.AlreadyExistsException;
 import org.apache.ratis.protocol.exceptions.GroupMismatchException;
 import org.apache.ratis.protocol.exceptions.NotLeaderException;
 import org.apache.ratis.protocol.exceptions.RaftException;
+import org.apache.ratis.protocol.exceptions.ReadException;
+import org.apache.ratis.protocol.exceptions.ReadIndexException;
 import org.apache.ratis.protocol.exceptions.ResourceUnavailableException;
 import org.apache.ratis.server.DivisionInfo;
 import org.apache.ratis.server.RaftServer;
@@ -92,6 +92,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -122,7 +123,6 @@ class RatisConsensus implements IConsensus {
   private static final int DEFAULT_PRIORITY = 0;
   private static final int LEADER_PRIORITY = 1;
 
-  /** TODO make it configurable */
   private static final int DEFAULT_WAIT_LEADER_READY_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(20);
 
   private final ScheduledExecutorService diskGuardian;
@@ -178,14 +178,14 @@ class RatisConsensus implements IConsensus {
   }
 
   @Override
-  public void start() throws IOException {
+  public synchronized void start() throws IOException {
     MetricService.getInstance().addMetricSet(this.ratisMetricSet);
     server.start();
     startSnapshotGuardian();
   }
 
   @Override
-  public void stop() throws IOException {
+  public synchronized void stop() throws IOException {
     diskGuardian.shutdown();
     try {
       diskGuardian.awaitTermination(5, TimeUnit.SECONDS);
@@ -249,53 +249,51 @@ class RatisConsensus implements IConsensus {
   }
 
   /**
-   * write will first send request to local server use method call if local server is not leader, it
-   * will use RaftClient to send RPC to read leader
+   * write will first send request to local server using local method call. If local server is not
+   * leader, it will use RaftClient to send RPC to read leader
    */
   @Override
-  public ConsensusWriteResponse write(
-      ConsensusGroupId consensusGroupId, IConsensusRequest IConsensusRequest) {
+  public TSStatus write(ConsensusGroupId groupId, IConsensusRequest request)
+      throws ConsensusException {
     // pre-condition: group exists and myself server serves this group
-    RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(consensusGroupId);
+    RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(groupId);
     RaftGroup raftGroup = getGroupInfo(raftGroupId);
     if (raftGroup == null || !raftGroup.getPeers().contains(myself)) {
-      return failedWrite(new ConsensusGroupNotExistException(consensusGroupId));
+      throw new ConsensusGroupNotExistException(groupId);
     }
 
     // current Peer is group leader and in ReadOnly State
-    if (isLeader(consensusGroupId) && Utils.rejectWrite()) {
+    if (isLeader(groupId) && Utils.rejectWrite()) {
       try {
         forceStepDownLeader(raftGroup);
       } catch (Exception e) {
         logger.warn("leader {} read only, force step down failed due to {}", myself, e);
       }
-      return failedWrite(new NodeReadOnlyException(myself));
+      return StatusUtils.getStatus(TSStatusCode.SYSTEM_READ_ONLY);
     }
 
     // serialize request into Message
-    Message message = new RequestMessage(IConsensusRequest);
+    Message message = new RequestMessage(request);
 
     // 1. first try the local server
     RaftClientRequest clientRequest =
         buildRawRequest(raftGroupId, message, RaftClientRequest.writeRequestType());
 
-    RaftClientReply localServerReply;
     RaftPeer suggestedLeader = null;
-    if (isLeader(consensusGroupId) && waitUntilLeaderReady(raftGroupId)) {
+    if (isLeader(groupId) && waitUntilLeaderReady(raftGroupId)) {
       try (AutoCloseable ignored =
           RatisMetricsManager.getInstance().startWriteLocallyTimer(consensusGroupType)) {
-        localServerReply = writeLocallyWithRetry(clientRequest);
+        RaftClientReply localServerReply = writeLocallyWithRetry(clientRequest);
         if (localServerReply.isSuccess()) {
           ResponseMessage responseMessage = (ResponseMessage) localServerReply.getMessage();
-          TSStatus writeStatus = (TSStatus) responseMessage.getContentHolder();
-          return ConsensusWriteResponse.newBuilder().setStatus(writeStatus).build();
+          return (TSStatus) responseMessage.getContentHolder();
         }
         NotLeaderException ex = localServerReply.getNotLeaderException();
-        if (ex != null) { // local server is not leader
+        if (ex != null) {
           suggestedLeader = ex.getSuggestedLeader();
         }
       } catch (Exception e) {
-        return failedWrite(new RatisRequestFailedException(e));
+        throw new RatisRequestFailedException(e);
       }
     }
 
@@ -306,54 +304,58 @@ class RatisConsensus implements IConsensus {
         RatisClient client = getRaftClient(raftGroup)) {
       RaftClientReply reply = writeRemotelyWithRetry(client, message);
       if (!reply.isSuccess()) {
-        return failedWrite(new RatisRequestFailedException(reply.getException()));
+        throw new RatisRequestFailedException(reply.getException());
       }
       writeResult = Utils.deserializeFrom(reply.getMessage().getContent().asReadOnlyByteBuffer());
     } catch (Exception e) {
-      return failedWrite(new RatisRequestFailedException(e));
+      throw new RatisRequestFailedException(e);
     }
 
     if (suggestedLeader != null) {
       TEndPoint leaderEndPoint = Utils.fromRaftPeerAddressToTEndPoint(suggestedLeader.getAddress());
       writeResult.setRedirectNode(new TEndPoint(leaderEndPoint.getIp(), leaderEndPoint.getPort()));
     }
-    return ConsensusWriteResponse.newBuilder().setStatus(writeResult).build();
+    return writeResult;
   }
 
-  /** Read directly from LOCAL COPY notice: May read stale data (not linearizable) */
+  /**
+   * Read directly from LOCAL COPY notice, although we do some optimizations to try to ensure
+   * linearizable (such as enforcing linearizable reads when the leader transfers), linearizable can
+   * be violated in some extreme cases.
+   */
   @Override
-  public ConsensusReadResponse read(
-      ConsensusGroupId consensusGroupId, IConsensusRequest IConsensusRequest) {
-    RaftGroupId groupId = Utils.fromConsensusGroupIdToRaftGroupId(consensusGroupId);
-    RaftGroup group = getGroupInfo(groupId);
+  public DataSet read(ConsensusGroupId groupId, IConsensusRequest request)
+      throws ConsensusException {
+    RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(groupId);
+    RaftGroup group = getGroupInfo(raftGroupId);
     if (group == null || !group.getPeers().contains(myself)) {
-      return failedRead(new ConsensusGroupNotExistException(consensusGroupId));
+      throw new ConsensusGroupNotExistException(groupId);
     }
 
     final boolean isLinearizableRead =
-        !canServeStaleRead.computeIfAbsent(consensusGroupId, id -> new AtomicBoolean(false)).get();
+        !canServeStaleRead.computeIfAbsent(groupId, id -> new AtomicBoolean(false)).get();
 
     RaftClientReply reply;
     try {
-      reply = doRead(groupId, IConsensusRequest, isLinearizableRead);
+      reply = doRead(raftGroupId, request, isLinearizableRead);
       // allow stale read if current linearizable read returns successfully
       if (isLinearizableRead) {
-        canServeStaleRead.get(consensusGroupId).set(true);
+        canServeStaleRead.get(groupId).set(true);
       }
-    } catch (Exception e) {
+    } catch (ReadException | ReadIndexException e) {
       if (isLinearizableRead) {
         // linearizable read failed. the RaftServer is recovering from Raft Log and cannot serve
         // read requests.
-        return failedRead(new RatisUnderRecoveryException(e));
+        throw new RatisUnderRecoveryException(e);
       } else {
-        return failedRead(new RatisRequestFailedException(e));
+        throw new RatisRequestFailedException(e);
       }
+    } catch (Exception e) {
+      throw new RatisRequestFailedException(e);
     }
-
     Message ret = reply.getMessage();
     ResponseMessage readResponseMessage = (ResponseMessage) ret;
-    DataSet dataSet = (DataSet) readResponseMessage.getContentHolder();
-    return ConsensusReadResponse.newBuilder().setDataSet(dataSet).build();
+    return (DataSet) readResponseMessage.getContentHolder();
   }
 
   /** return a success raft client reply or throw an Exception */
@@ -388,24 +390,22 @@ class RatisConsensus implements IConsensus {
    * register self to the RaftGroup
    */
   @Override
-  public ConsensusGenericResponse createPeer(ConsensusGroupId groupId, List<Peer> peers) {
+  public void createLocalPeer(ConsensusGroupId groupId, List<Peer> peers)
+      throws ConsensusException {
     RaftGroup group = buildRaftGroup(groupId, peers);
-    RaftClientReply reply;
     RaftGroup clientGroup =
         group.getPeers().isEmpty() ? RaftGroup.valueOf(group.getGroupId(), myself) : group;
     try (RatisClient client = getRaftClient(clientGroup)) {
-      reply = client.getRaftClient().getGroupManagementApi(myself.getId()).add(group);
+      RaftClientReply reply =
+          client.getRaftClient().getGroupManagementApi(myself.getId()).add(group);
       if (!reply.isSuccess()) {
-        return failed(new RatisRequestFailedException(reply.getException()));
+        throw new RatisRequestFailedException(reply.getException());
       }
     } catch (AlreadyExistsException e) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new ConsensusGroupAlreadyExistException(groupId))
-          .build();
+      throw new ConsensusGroupAlreadyExistException(groupId);
     } catch (Exception e) {
-      return failed(new RatisRequestFailedException(e));
+      throw new RatisRequestFailedException(e);
     }
-    return ConsensusGenericResponse.newBuilder().setSuccess(reply.isSuccess()).build();
   }
 
   /**
@@ -416,7 +416,7 @@ class RatisConsensus implements IConsensus {
    * clean up
    */
   @Override
-  public ConsensusGenericResponse deletePeer(ConsensusGroupId groupId) {
+  public void deleteLocalPeer(ConsensusGroupId groupId) throws ConsensusException {
     RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(groupId);
 
     // send remove group to myself
@@ -432,17 +432,13 @@ class RatisConsensus implements IConsensus {
                   true,
                   false));
       if (!reply.isSuccess()) {
-        return failed(new RatisRequestFailedException(reply.getException()));
+        throw new RatisRequestFailedException(reply.getException());
       }
     } catch (GroupMismatchException e) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
+      throw new ConsensusGroupNotExistException(groupId);
     } catch (IOException e) {
-      return failed(new RatisRequestFailedException(e));
+      throw new RatisRequestFailedException(e);
     }
-
-    return ConsensusGenericResponse.newBuilder().setSuccess(reply.isSuccess()).build();
   }
 
   /**
@@ -452,32 +448,25 @@ class RatisConsensus implements IConsensus {
    * change
    */
   @Override
-  public ConsensusGenericResponse addPeer(ConsensusGroupId groupId, Peer peer) {
+  public void addRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException {
     RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(groupId);
-    RaftGroup group = getGroupInfo(raftGroupId);
-    RaftPeer peerToAdd = Utils.fromPeerAndPriorityToRaftPeer(peer, DEFAULT_PRIORITY);
 
+    RaftGroup group = getGroupInfo(raftGroupId);
     // pre-conditions: group exists and myself in this group
     if (group == null || !group.getPeers().contains(myself)) {
-      return failed(new ConsensusGroupNotExistException(groupId));
+      throw new ConsensusGroupNotExistException(groupId);
     }
 
+    RaftPeer peerToAdd = Utils.fromPeerAndPriorityToRaftPeer(peer, DEFAULT_PRIORITY);
     // pre-condition: peer not in this group
     if (group.getPeers().contains(peerToAdd)) {
-      return failed(new PeerAlreadyInConsensusGroupException(groupId, peer));
+      throw new PeerAlreadyInConsensusGroupException(groupId, peer);
     }
 
     List<RaftPeer> newConfig = new ArrayList<>(group.getPeers());
     newConfig.add(peerToAdd);
 
-    RaftClientReply reply;
-    try {
-      reply = sendReconfiguration(RaftGroup.valueOf(raftGroupId, newConfig));
-    } catch (RatisRequestFailedException e) {
-      return failed(e);
-    }
-
-    return ConsensusGenericResponse.newBuilder().setSuccess(reply.isSuccess()).build();
+    sendReconfiguration(RaftGroup.valueOf(raftGroupId, newConfig));
   }
 
   /**
@@ -487,18 +476,18 @@ class RatisConsensus implements IConsensus {
    * change
    */
   @Override
-  public ConsensusGenericResponse removePeer(ConsensusGroupId groupId, Peer peer) {
+  public void removeRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException {
     RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(groupId);
     RaftGroup group = getGroupInfo(raftGroupId);
     RaftPeer peerToRemove = Utils.fromPeerAndPriorityToRaftPeer(peer, DEFAULT_PRIORITY);
 
     // pre-conditions: group exists and myself in this group
     if (group == null || !group.getPeers().contains(myself)) {
-      return failed(new ConsensusGroupNotExistException(groupId));
+      throw new ConsensusGroupNotExistException(groupId);
     }
     // pre-condition: peer is a member of groupId
     if (!group.getPeers().contains(peerToRemove)) {
-      return failed(new PeerNotInConsensusGroupException(groupId, myself));
+      throw new PeerNotInConsensusGroupException(groupId, myself.getAddress());
     }
 
     // update group peer information
@@ -507,38 +496,7 @@ class RatisConsensus implements IConsensus {
             .filter(raftPeer -> !raftPeer.equals(peerToRemove))
             .collect(Collectors.toList());
 
-    RaftClientReply reply;
-    try {
-      reply = sendReconfiguration(RaftGroup.valueOf(raftGroupId, newConfig));
-    } catch (RatisRequestFailedException e) {
-      return failed(e);
-    }
-
-    return ConsensusGenericResponse.newBuilder().setSuccess(reply.isSuccess()).build();
-  }
-
-  @Override
-  public ConsensusGenericResponse updatePeer(ConsensusGroupId groupId, Peer oldPeer, Peer newPeer) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(false).build();
-  }
-
-  @Override
-  public ConsensusGenericResponse changePeer(ConsensusGroupId groupId, List<Peer> newPeers) {
-    RaftGroup raftGroup = buildRaftGroup(groupId, newPeers);
-
-    // pre-conditions: myself in this group
-    if (!raftGroup.getPeers().contains(myself)) {
-      return failed(new ConsensusGroupNotExistException(groupId));
-    }
-
-    // add RaftPeer myself to this RaftGroup
-    RaftClientReply reply;
-    try {
-      reply = sendReconfiguration(raftGroup);
-    } catch (RatisRequestFailedException e) {
-      return failed(e);
-    }
-    return ConsensusGenericResponse.newBuilder().setSuccess(reply.isSuccess()).build();
+    sendReconfiguration(RaftGroup.valueOf(raftGroupId, newConfig));
   }
 
   /**
@@ -554,16 +512,13 @@ class RatisConsensus implements IConsensus {
    * election. In this election, the newLeader peer with priority 1 is guaranteed to be elected.
    */
   @Override
-  public ConsensusGenericResponse transferLeader(ConsensusGroupId groupId, Peer newLeader) {
+  public void transferLeader(ConsensusGroupId groupId, Peer newLeader) throws ConsensusException {
 
     // first fetch the newest information
-
     RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(groupId);
-    RaftGroup raftGroup = getGroupInfo(raftGroupId);
-
-    if (raftGroup == null) {
-      return failed(new ConsensusGroupNotExistException(groupId));
-    }
+    RaftGroup raftGroup =
+        Optional.ofNullable(getGroupInfo(raftGroupId))
+            .orElseThrow(() -> new ConsensusGroupNotExistException(groupId));
 
     RaftPeer newRaftLeader = Utils.fromPeerAndPriorityToRaftPeer(newLeader, LEADER_PRIORITY);
 
@@ -586,17 +541,16 @@ class RatisConsensus implements IConsensus {
       RaftClientReply configChangeReply =
           client.getRaftClient().admin().setConfiguration(newConfiguration);
       if (!configChangeReply.isSuccess()) {
-        return failed(new RatisRequestFailedException(configChangeReply.getException()));
+        throw new RatisRequestFailedException(configChangeReply.getException());
       }
 
       reply = transferLeader(raftGroup, newRaftLeader);
       if (!reply.isSuccess()) {
-        return failed(new RatisRequestFailedException(reply.getException()));
+        throw new RatisRequestFailedException(reply.getException());
       }
     } catch (Exception e) {
-      return failed(new RatisRequestFailedException(e));
+      throw new RatisRequestFailedException(e);
     }
-    return ConsensusGenericResponse.newBuilder().setSuccess(reply.isSuccess()).build();
   }
 
   private void forceStepDownLeader(RaftGroup group) throws Exception {
@@ -607,7 +561,6 @@ class RatisConsensus implements IConsensus {
 
   private RaftClientReply transferLeader(RaftGroup group, RaftPeer newLeader) throws Exception {
     try (RatisClient client = getRaftClient(group)) {
-      // TODO tuning for timeoutMs
       return client
           .getRaftClient()
           .admin()
@@ -618,16 +571,25 @@ class RatisConsensus implements IConsensus {
   @Override
   public boolean isLeader(ConsensusGroupId groupId) {
     RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(groupId);
-
-    boolean isLeader;
     try {
-      isLeader = server.getDivision(raftGroupId).getInfo().isLeader();
+      return server.getDivision(raftGroupId).getInfo().isLeader();
     } catch (IOException exception) {
       // if the read fails, simply return not leader
       logger.info("isLeader request failed with exception: ", exception);
-      isLeader = false;
+      return false;
+    }
+  }
+
+  @Override
+  public boolean isLeaderReady(ConsensusGroupId groupId) {
+    RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(groupId);
+    try {
+      return server.getDivision(raftGroupId).getInfo().isLeaderReady();
+    } catch (IOException exception) {
+      // if the read fails, simply return not ready
+      logger.info("isLeaderReady request failed with exception: ", exception);
+      return false;
     }
-    return isLeader;
   }
 
   private boolean waitUntilLeaderReady(RaftGroupId groupId) {
@@ -651,7 +613,7 @@ class RatisConsensus implements IConsensus {
       }
     } catch (InterruptedException e) {
       Thread.currentThread().interrupt();
-      logger.warn("Unexpected interruption", e);
+      logger.warn("Unexpected interruption when waitUntilLeaderReady", e);
       return false;
     }
     return divisionInfo.isLeader();
@@ -691,12 +653,11 @@ class RatisConsensus implements IConsensus {
   }
 
   @Override
-  public ConsensusGenericResponse triggerSnapshot(ConsensusGroupId groupId) {
+  public void triggerSnapshot(ConsensusGroupId groupId) throws ConsensusException {
     RaftGroupId raftGroupId = Utils.fromConsensusGroupIdToRaftGroupId(groupId);
     RaftGroup groupInfo = getGroupInfo(raftGroupId);
-
     if (groupInfo == null || !groupInfo.getPeers().contains(myself)) {
-      return failed(new ConsensusGroupNotExistException(groupId));
+      throw new ConsensusGroupNotExistException(groupId);
     }
 
     // TODO tuning snapshot create timeout
@@ -708,13 +669,11 @@ class RatisConsensus implements IConsensus {
     try {
       reply = server.snapshotManagement(request);
       if (!reply.isSuccess()) {
-        return failed(new RatisRequestFailedException(reply.getException()));
+        throw new RatisRequestFailedException(reply.getException());
       }
     } catch (IOException ioException) {
-      return failed(new RatisRequestFailedException(ioException));
+      throw new RatisRequestFailedException(ioException);
     }
-
-    return ConsensusGenericResponse.newBuilder().setSuccess(reply.isSuccess()).build();
   }
 
   private void triggerSnapshotByCustomize() {
@@ -741,15 +700,11 @@ class RatisConsensus implements IConsensus {
             currentDirLength,
             filesCount);
 
-        final ConsensusGenericResponse consensusGenericResponse =
-            triggerSnapshot(Utils.fromRaftGroupIdToConsensusGroupId(raftGroupId));
-        if (consensusGenericResponse.isSuccess()) {
+        try {
+          triggerSnapshot(Utils.fromRaftGroupIdToConsensusGroupId(raftGroupId));
           logger.info("Raft group {} took snapshot successfully", raftGroupId);
-        } else {
-          logger.warn(
-              "Raft group {} failed to take snapshot due to",
-              raftGroupId,
-              consensusGenericResponse.getException());
+        } catch (ConsensusException e) {
+          logger.warn("Raft group {} failed to take snapshot due to", raftGroupId, e);
         }
       }
     }
@@ -761,21 +716,6 @@ class RatisConsensus implements IConsensus {
         diskGuardian, this::triggerSnapshotByCustomize, 0, delay, TimeUnit.SECONDS);
   }
 
-  private ConsensusGenericResponse failed(ConsensusException e) {
-    logger.debug("{} request failed with exception {}", this, e);
-    return ConsensusGenericResponse.newBuilder().setSuccess(false).setException(e).build();
-  }
-
-  private ConsensusWriteResponse failedWrite(ConsensusException e) {
-    logger.debug("{} write request failed with exception {}", this, e);
-    return ConsensusWriteResponse.newBuilder().setException(e).build();
-  }
-
-  private ConsensusReadResponse failedRead(ConsensusException e) {
-    logger.debug("{} read request failed with exception {}", this, e);
-    return ConsensusReadResponse.newBuilder().setException(e).build();
-  }
-
   private RaftClientRequest buildRawRequest(
       RaftGroupId groupId, Message message, RaftClientRequest.Type type) {
     return RaftClientRequest.newBuilder()
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 fe96ddfa918..59f6cccd6f8 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
@@ -25,15 +25,15 @@ import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import org.apache.iotdb.commons.consensus.DataRegionId;
 import org.apache.iotdb.commons.service.metric.PerformanceOverviewMetrics;
 import org.apache.iotdb.commons.utils.FileUtils;
+import org.apache.iotdb.commons.utils.StatusUtils;
 import org.apache.iotdb.consensus.IConsensus;
 import org.apache.iotdb.consensus.IStateMachine;
 import org.apache.iotdb.consensus.IStateMachine.Registry;
+import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.common.request.IConsensusRequest;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupNotExistException;
 import org.apache.iotdb.consensus.exception.IllegalPeerEndpointException;
@@ -51,6 +51,7 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -67,7 +68,8 @@ class SimpleConsensus implements IConsensus {
   private final int thisNodeId;
   private final File storageDir;
   private final IStateMachine.Registry registry;
-  private final Map<ConsensusGroupId, SimpleServerImpl> stateMachineMap = new ConcurrentHashMap<>();
+  private final Map<ConsensusGroupId, SimpleConsensusServerImpl> stateMachineMap =
+      new ConcurrentHashMap<>();
   private static final PerformanceOverviewMetrics PERFORMANCE_OVERVIEW_METRICS =
       PerformanceOverviewMetrics.getInstance();
 
@@ -79,14 +81,14 @@ class SimpleConsensus implements IConsensus {
   }
 
   @Override
-  public void start() throws IOException {
+  public synchronized void start() throws IOException {
     initAndRecover();
   }
 
   private void initAndRecover() throws IOException {
     if (!storageDir.exists()) {
       if (!storageDir.mkdirs()) {
-        logger.warn("Unable to create consensus dir at {}", storageDir);
+        throw new IOException(String.format("Unable to create consensus dir at %s", storageDir));
       }
     } else {
       try (DirectoryStream<Path> stream = Files.newDirectoryStream(storageDir.toPath())) {
@@ -95,8 +97,8 @@ class SimpleConsensus implements IConsensus {
           ConsensusGroupId consensusGroupId =
               ConsensusGroupId.Factory.create(
                   Integer.parseInt(items[0]), Integer.parseInt(items[1]));
-          SimpleServerImpl consensus =
-              new SimpleServerImpl(
+          SimpleConsensusServerImpl consensus =
+              new SimpleConsensusServerImpl(
                   new Peer(consensusGroupId, thisNodeId, thisNode),
                   registry.apply(consensusGroupId));
           stateMachineMap.put(consensusGroupId, consensus);
@@ -107,24 +109,20 @@ class SimpleConsensus implements IConsensus {
   }
 
   @Override
-  public void stop() throws IOException {
-    stateMachineMap.values().parallelStream().forEach(SimpleServerImpl::stop);
+  public synchronized void stop() throws IOException {
+    stateMachineMap.values().parallelStream().forEach(SimpleConsensusServerImpl::stop);
   }
 
   @Override
-  public ConsensusWriteResponse write(ConsensusGroupId groupId, IConsensusRequest request) {
-    SimpleServerImpl impl = stateMachineMap.get(groupId);
-    if (impl == null) {
-      return ConsensusWriteResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
-    }
-
-    TSStatus status;
+  public TSStatus write(ConsensusGroupId groupId, IConsensusRequest request)
+      throws ConsensusException {
+    SimpleConsensusServerImpl impl =
+        Optional.ofNullable(stateMachineMap.get(groupId))
+            .orElseThrow(() -> new ConsensusGroupNotExistException(groupId));
     if (impl.isReadOnly()) {
-      status = new TSStatus(TSStatusCode.SYSTEM_READ_ONLY.getStatusCode());
-      status.setMessage("Fail to do non-query operations because system is read-only.");
+      return StatusUtils.getStatus(TSStatusCode.SYSTEM_READ_ONLY);
     } else {
+      TSStatus status;
       if (groupId instanceof DataRegionId) {
         long startWriteTime = System.nanoTime();
         status = impl.write(request);
@@ -133,58 +131,59 @@ class SimpleConsensus implements IConsensus {
       } else {
         status = impl.write(request);
       }
+      return status;
     }
-    return ConsensusWriteResponse.newBuilder().setStatus(status).build();
   }
 
   @Override
-  public ConsensusReadResponse read(ConsensusGroupId groupId, IConsensusRequest request) {
-    SimpleServerImpl impl = stateMachineMap.get(groupId);
-    if (impl == null) {
-      return ConsensusReadResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
-    }
-    return ConsensusReadResponse.newBuilder().setDataSet(impl.read(request)).build();
+  public DataSet read(ConsensusGroupId groupId, IConsensusRequest request)
+      throws ConsensusException {
+    return Optional.ofNullable(stateMachineMap.get(groupId))
+        .orElseThrow(() -> new ConsensusGroupNotExistException(groupId))
+        .read(request);
   }
 
+  @SuppressWarnings("java:S2201")
   @Override
-  public ConsensusGenericResponse createPeer(ConsensusGroupId groupId, List<Peer> peers) {
+  public void createLocalPeer(ConsensusGroupId groupId, List<Peer> peers)
+      throws ConsensusException {
     int consensusGroupSize = peers.size();
     if (consensusGroupSize != 1) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new IllegalPeerNumException(consensusGroupSize))
-          .build();
+      throw new IllegalPeerNumException(consensusGroupSize);
     }
     if (!peers.contains(new Peer(groupId, thisNodeId, thisNode))) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new IllegalPeerEndpointException(thisNode, peers))
-          .build();
+      throw new IllegalPeerEndpointException(thisNode, peers);
     }
     AtomicBoolean exist = new AtomicBoolean(true);
-    stateMachineMap.computeIfAbsent(
-        groupId,
-        k -> {
-          exist.set(false);
-          SimpleServerImpl impl = new SimpleServerImpl(peers.get(0), registry.apply(groupId));
-          impl.start();
-          String path = buildPeerDir(groupId);
-          File file = new File(path);
-          if (!file.mkdirs()) {
-            logger.warn("Unable to create consensus dir for group {} at {}", groupId, path);
-          }
-          return impl;
-        });
+    Optional.ofNullable(
+            stateMachineMap.computeIfAbsent(
+                groupId,
+                k -> {
+                  exist.set(false);
+
+                  String path = buildPeerDir(groupId);
+                  File file = new File(path);
+                  if (!file.mkdirs()) {
+                    logger.warn("Unable to create consensus dir for group {} at {}", groupId, path);
+                    return null;
+                  }
+
+                  SimpleConsensusServerImpl impl =
+                      new SimpleConsensusServerImpl(peers.get(0), registry.apply(groupId));
+                  impl.start();
+                  return impl;
+                }))
+        .orElseThrow(
+            () ->
+                new ConsensusException(
+                    String.format("Unable to create consensus dir for group %s", groupId)));
     if (exist.get()) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new ConsensusGroupAlreadyExistException(groupId))
-          .build();
+      throw new ConsensusGroupAlreadyExistException(groupId);
     }
-    return ConsensusGenericResponse.newBuilder().setSuccess(true).build();
   }
 
   @Override
-  public ConsensusGenericResponse deletePeer(ConsensusGroupId groupId) {
+  public void deleteLocalPeer(ConsensusGroupId groupId) throws ConsensusException {
     AtomicBoolean exist = new AtomicBoolean(false);
     stateMachineMap.computeIfPresent(
         groupId,
@@ -194,47 +193,38 @@ class SimpleConsensus implements IConsensus {
           FileUtils.deleteDirectory(new File(buildPeerDir(groupId)));
           return null;
         });
-
     if (!exist.get()) {
-      return ConsensusGenericResponse.newBuilder()
-          .setException(new ConsensusGroupNotExistException(groupId))
-          .build();
+      throw new ConsensusGroupNotExistException(groupId);
     }
-    return ConsensusGenericResponse.newBuilder().setSuccess(true).build();
   }
 
   @Override
-  public ConsensusGenericResponse addPeer(ConsensusGroupId groupId, Peer peer) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(false).build();
+  public void addRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException {
+    throw new ConsensusException("SimpleConsensus does not support membership changes");
   }
 
   @Override
-  public ConsensusGenericResponse removePeer(ConsensusGroupId groupId, Peer peer) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(false).build();
+  public void removeRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException {
+    throw new ConsensusException("SimpleConsensus does not support membership changes");
   }
 
   @Override
-  public ConsensusGenericResponse updatePeer(ConsensusGroupId groupId, Peer oldPeer, Peer newPeer) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(false).build();
+  public void transferLeader(ConsensusGroupId groupId, Peer newLeader) throws ConsensusException {
+    throw new ConsensusException("SimpleConsensus does not support leader transfer");
   }
 
   @Override
-  public ConsensusGenericResponse changePeer(ConsensusGroupId groupId, List<Peer> newPeers) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(false).build();
+  public void triggerSnapshot(ConsensusGroupId groupId) throws ConsensusException {
+    throw new ConsensusException("SimpleConsensus does not support snapshot trigger currently");
   }
 
   @Override
-  public ConsensusGenericResponse transferLeader(ConsensusGroupId groupId, Peer newLeader) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(false).build();
-  }
-
-  @Override
-  public ConsensusGenericResponse triggerSnapshot(ConsensusGroupId groupId) {
-    return ConsensusGenericResponse.newBuilder().setSuccess(false).build();
+  public boolean isLeader(ConsensusGroupId groupId) {
+    return true;
   }
 
   @Override
-  public boolean isLeader(ConsensusGroupId groupId) {
+  public boolean isLeaderReady(ConsensusGroupId groupId) {
     return true;
   }
 
diff --git a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleServerImpl.java b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleConsensusServerImpl.java
similarity index 94%
rename from iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleServerImpl.java
rename to iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleConsensusServerImpl.java
index 3f2b68857cb..b4d8fe87040 100644
--- a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleServerImpl.java
+++ b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/simple/SimpleConsensusServerImpl.java
@@ -27,12 +27,12 @@ import org.apache.iotdb.consensus.common.request.IConsensusRequest;
 
 import java.io.File;
 
-public class SimpleServerImpl implements IStateMachine {
+public class SimpleConsensusServerImpl implements IStateMachine {
 
   private final Peer peer;
   private final IStateMachine stateMachine;
 
-  public SimpleServerImpl(Peer peer, IStateMachine stateMachine) {
+  public SimpleConsensusServerImpl(Peer peer, IStateMachine stateMachine) {
     this.peer = peer;
     this.stateMachine = stateMachine;
   }
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 916f91f3ac5..39eab9c5dd7 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
@@ -27,6 +27,7 @@ import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.consensus.common.ConsensusGroup;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.consensus.iot.util.TestEntry;
 import org.apache.iotdb.consensus.iot.util.TestStateMachine;
 import org.apache.iotdb.tsfile.utils.PublicBAOS;
@@ -157,11 +158,12 @@ public class ReplicateTest {
    * The three nodes use the requests in the queue to replicate the requests to the other two nodes.
    */
   @Test
-  public void replicateUsingQueueTest() throws IOException, InterruptedException {
+  public void replicateUsingQueueTest()
+      throws IOException, InterruptedException, ConsensusException {
     logger.info("Start ReplicateUsingQueueTest");
-    servers.get(0).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(1).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(2).createPeer(group.getGroupId(), group.getPeers());
+    servers.get(0).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(1).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(2).createLocalPeer(group.getGroupId(), group.getPeers());
 
     Assert.assertEquals(0, servers.get(0).getImpl(gid).getSearchIndex());
     Assert.assertEquals(0, servers.get(1).getImpl(gid).getSearchIndex());
@@ -235,10 +237,10 @@ public class ReplicateTest {
    * nodes finally consistent.
    */
   @Test
-  public void replicateUsingWALTest() throws IOException, InterruptedException {
+  public void replicateUsingWALTest() throws IOException, InterruptedException, ConsensusException {
     logger.info("Start ReplicateUsingWALTest");
-    servers.get(0).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(1).createPeer(group.getGroupId(), group.getPeers());
+    servers.get(0).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(1).createLocalPeer(group.getGroupId(), group.getPeers());
 
     Assert.assertEquals(0, servers.get(0).getImpl(gid).getSearchIndex());
     Assert.assertEquals(0, servers.get(1).getImpl(gid).getSearchIndex());
@@ -256,7 +258,7 @@ public class ReplicateTest {
     stopServer();
     initServer();
 
-    servers.get(2).createPeer(group.getGroupId(), group.getPeers());
+    servers.get(2).createLocalPeer(group.getGroupId(), group.getPeers());
 
     Assert.assertEquals(peers, servers.get(0).getImpl(gid).getConfiguration());
     Assert.assertEquals(peers, servers.get(1).getImpl(gid).getConfiguration());
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 5afee66ee1a..021a40af947 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
@@ -26,9 +26,13 @@ import org.apache.iotdb.commons.consensus.DataRegionId;
 import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.consensus.IConsensus;
 import org.apache.iotdb.consensus.common.Peer;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
+import org.apache.iotdb.consensus.exception.ConsensusException;
+import org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupModifyPeerException;
+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.util.TestStateMachine;
 
 import org.apache.ratis.util.FileUtils;
@@ -41,6 +45,8 @@ import java.io.File;
 import java.io.IOException;
 import java.util.Collections;
 
+import static org.junit.Assert.assertTrue;
+
 public class StabilityTest {
 
   private final ConsensusGroupId dataRegionId = new DataRegionId(1);
@@ -49,7 +55,7 @@ public class StabilityTest {
 
   private IConsensus consensusImpl;
 
-  private final int basePort = 9000;
+  private final int basePort = 6667;
 
   public void constructConsensus() throws IOException {
     consensusImpl =
@@ -84,34 +90,102 @@ public class StabilityTest {
 
   @Test
   public void allTest() throws Exception {
+    addConsensusGroup();
+    removeConsensusGroup();
     peerTest();
+    transferLeader();
     snapshotTest();
     snapshotUpgradeTest();
   }
 
+  public void addConsensusGroup() {
+    try {
+      consensusImpl.createLocalPeer(
+          dataRegionId,
+          Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
+    } catch (ConsensusException e) {
+      Assert.fail();
+    }
+
+    try {
+      consensusImpl.createLocalPeer(
+          dataRegionId,
+          Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
+      Assert.fail();
+    } catch (ConsensusException e) {
+      assertTrue(e instanceof ConsensusGroupAlreadyExistException);
+    }
+
+    try {
+      consensusImpl.createLocalPeer(dataRegionId, Collections.emptyList());
+      Assert.fail();
+    } catch (ConsensusException e) {
+      assertTrue(e instanceof IllegalPeerNumException);
+    }
+
+    try {
+      consensusImpl.createLocalPeer(
+          dataRegionId,
+          Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.1", 6667))));
+      Assert.fail();
+    } catch (ConsensusException e) {
+      assertTrue(e instanceof IllegalPeerEndpointException);
+    }
+
+    try {
+      consensusImpl.deleteLocalPeer(dataRegionId);
+    } catch (ConsensusException e) {
+      Assert.fail();
+    }
+  }
+
+  public void removeConsensusGroup() {
+    try {
+      consensusImpl.deleteLocalPeer(dataRegionId);
+      Assert.fail();
+    } catch (ConsensusException e) {
+      assertTrue(e instanceof ConsensusGroupNotExistException);
+    }
+
+    try {
+      consensusImpl.createLocalPeer(
+          dataRegionId,
+          Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
+      consensusImpl.deleteLocalPeer(dataRegionId);
+    } catch (ConsensusException e) {
+      Assert.fail();
+    }
+  }
+
   public void peerTest() throws Exception {
-    consensusImpl.createPeer(
+    consensusImpl.createLocalPeer(
         dataRegionId,
         Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", basePort))));
 
-    consensusImpl.deletePeer(dataRegionId);
+    consensusImpl.deleteLocalPeer(dataRegionId);
 
     consensusImpl.stop();
     consensusImpl = null;
 
     constructConsensus();
+    consensusImpl.createLocalPeer(
+        dataRegionId,
+        Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", basePort))));
+    consensusImpl.deleteLocalPeer(dataRegionId);
+  }
 
-    ConsensusGenericResponse response =
-        consensusImpl.createPeer(
-            dataRegionId,
-            Collections.singletonList(
-                new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", basePort))));
-    Assert.assertTrue(response.isSuccess());
-    consensusImpl.deletePeer(dataRegionId);
+  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.");
+    } catch (ConsensusException e) {
+      // not handle
+    }
   }
 
-  public void snapshotTest() throws IOException {
-    consensusImpl.createPeer(
+  public void snapshotTest() throws ConsensusException {
+    consensusImpl.createLocalPeer(
         dataRegionId,
         Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", basePort))));
     consensusImpl.triggerSnapshot(dataRegionId);
@@ -132,11 +206,11 @@ public class StabilityTest {
     Assert.assertNotNull(versionFiles2);
     Assert.assertEquals(1, versionFiles2.length);
     Assert.assertNotEquals(versionFiles1[0].getName(), versionFiles2[0].getName());
-    consensusImpl.deletePeer(dataRegionId);
+    consensusImpl.deleteLocalPeer(dataRegionId);
   }
 
   public void snapshotUpgradeTest() throws Exception {
-    consensusImpl.createPeer(
+    consensusImpl.createLocalPeer(
         dataRegionId,
         Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", basePort))));
     consensusImpl.triggerSnapshot(dataRegionId);
@@ -166,6 +240,6 @@ public class StabilityTest {
     Assert.assertEquals(
         oldSnapshotIndex + 1,
         Long.parseLong(snapshotFiles[0].getName().replaceAll(".*[^\\d](?=(\\d+))", "")));
-    consensusImpl.deletePeer(dataRegionId);
+    consensusImpl.deleteLocalPeer(dataRegionId);
   }
 }
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 6d6b1742603..18934e15b28 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
@@ -19,17 +19,20 @@
 
 package org.apache.iotdb.consensus.ratis;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import org.apache.iotdb.consensus.IConsensus;
 import org.apache.iotdb.consensus.IStateMachine;
 import org.apache.iotdb.consensus.common.ConsensusGroup;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.common.request.ByteBufferConsensusRequest;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.consensus.config.RatisConfig;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
+import org.apache.iotdb.consensus.exception.ConsensusGroupNotExistException;
+import org.apache.iotdb.consensus.exception.PeerAlreadyInConsensusGroupException;
+import org.apache.iotdb.consensus.exception.PeerNotInConsensusGroupException;
+import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.apache.ratis.util.TimeDuration;
 import org.junit.After;
@@ -38,7 +41,6 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.io.IOException;
-import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
@@ -101,9 +103,9 @@ public class RatisConsensusTest {
 
   @Test
   public void basicConsensus3Copy() throws Exception {
-    servers.get(0).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(1).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(2).createPeer(group.getGroupId(), group.getPeers());
+    servers.get(0).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(1).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(2).createLocalPeer(group.getGroupId(), group.getPeers());
 
     doConsensus(servers.get(0), group.getGroupId(), 10, 10);
   }
@@ -112,19 +114,22 @@ public class RatisConsensusTest {
   public void addMemberToGroup() throws Exception {
     List<Peer> original = peers.subList(0, 1);
 
-    servers.get(0).createPeer(group.getGroupId(), original);
+    servers.get(0).createLocalPeer(group.getGroupId(), original);
     doConsensus(servers.get(0), group.getGroupId(), 10, 10);
 
-    ConsensusGenericResponse resp = servers.get(0).createPeer(group.getGroupId(), original);
-    Assert.assertFalse(resp.isSuccess());
-    Assert.assertTrue(resp.getException() instanceof ConsensusGroupAlreadyExistException);
+    try {
+      servers.get(0).createLocalPeer(group.getGroupId(), original);
+      Assert.fail();
+    } catch (ConsensusException e) {
+      Assert.assertTrue(e instanceof ConsensusGroupAlreadyExistException);
+    }
 
     // add 2 members
-    servers.get(1).createPeer(group.getGroupId(), Collections.emptyList());
-    servers.get(0).addPeer(group.getGroupId(), peers.get(1));
+    servers.get(1).createLocalPeer(group.getGroupId(), peers.subList(1, 2));
+    servers.get(0).addRemotePeer(group.getGroupId(), peers.get(1));
 
-    servers.get(2).createPeer(group.getGroupId(), Collections.emptyList());
-    servers.get(0).changePeer(group.getGroupId(), peers);
+    servers.get(2).createLocalPeer(group.getGroupId(), peers.subList(2, 3));
+    servers.get(0).addRemotePeer(group.getGroupId(), peers.get(2));
 
     Assert.assertEquals(
         3, ((TestUtils.IntegerCounter) stateMachines.get(0)).getConfiguration().size());
@@ -133,39 +138,69 @@ public class RatisConsensusTest {
 
   @Test
   public void removeMemberFromGroup() throws Exception {
-    servers.get(0).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(1).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(2).createPeer(group.getGroupId(), group.getPeers());
+    try {
+      servers.get(0).deleteLocalPeer(group.getGroupId());
+      Assert.fail();
+    } catch (ConsensusException e) {
+      Assert.assertTrue(e instanceof ConsensusGroupNotExistException);
+    }
+    servers.get(0).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(1).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(2).createLocalPeer(group.getGroupId(), group.getPeers());
 
     doConsensus(servers.get(0), group.getGroupId(), 10, 10);
 
     servers.get(0).transferLeader(gid, peers.get(0));
-    servers.get(0).removePeer(gid, peers.get(1));
-    servers.get(1).deletePeer(gid);
-    servers.get(0).removePeer(gid, peers.get(2));
-    servers.get(2).deletePeer(gid);
+    servers.get(0).removeRemotePeer(gid, peers.get(1));
+    servers.get(1).deleteLocalPeer(gid);
+    servers.get(0).removeRemotePeer(gid, peers.get(2));
+    servers.get(2).deleteLocalPeer(gid);
 
     doConsensus(servers.get(0), group.getGroupId(), 10, 20);
   }
 
   @Test
   public void oneMemberGroupChange() throws Exception {
-    servers.get(0).createPeer(group.getGroupId(), peers.subList(0, 1));
+    try {
+      servers.get(0).addRemotePeer(group.getGroupId(), peers.get(0));
+      Assert.fail();
+    } catch (ConsensusException e) {
+      Assert.assertTrue(e instanceof ConsensusGroupNotExistException);
+    }
+    servers.get(0).createLocalPeer(group.getGroupId(), peers.subList(0, 1));
     doConsensus(servers.get(0), group.getGroupId(), 10, 10);
 
-    servers.get(1).createPeer(group.getGroupId(), Collections.emptyList());
-    servers.get(0).addPeer(group.getGroupId(), peers.get(1));
-    servers.get(1).transferLeader(group.getGroupId(), peers.get(1));
-    servers.get(0).removePeer(group.getGroupId(), peers.get(0));
+    servers.get(1).createLocalPeer(group.getGroupId(), peers.subList(1, 2));
+    servers.get(0).addRemotePeer(group.getGroupId(), peers.get(1));
+    try {
+      servers.get(0).addRemotePeer(group.getGroupId(), peers.get(1));
+      Assert.fail();
+    } catch (ConsensusException e) {
+      Assert.assertTrue(e instanceof PeerAlreadyInConsensusGroupException);
+    }
+    servers.get(0).transferLeader(group.getGroupId(), peers.get(1));
+    servers.get(1).removeRemotePeer(group.getGroupId(), peers.get(0));
+    try {
+      servers.get(1).removeRemotePeer(group.getGroupId(), peers.get(0));
+      Assert.fail();
+    } catch (ConsensusException e) {
+      Assert.assertTrue(e instanceof PeerNotInConsensusGroupException);
+    }
     Assert.assertEquals(servers.get(1).getLeader(gid).getNodeId(), peers.get(1).getNodeId());
-    servers.get(0).deletePeer(group.getGroupId());
+    servers.get(0).deleteLocalPeer(group.getGroupId());
+    try {
+      servers.get(0).deleteLocalPeer(group.getGroupId());
+      Assert.fail();
+    } catch (ConsensusException e) {
+      Assert.assertTrue(e instanceof ConsensusGroupNotExistException);
+    }
   }
 
   @Test
   public void crashAndStart() throws Exception {
-    servers.get(0).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(1).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(2).createPeer(group.getGroupId(), group.getPeers());
+    servers.get(0).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(1).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(2).createLocalPeer(group.getGroupId(), group.getPeers());
 
     // 200 operation will trigger snapshot & purge
     doConsensus(servers.get(0), group.getGroupId(), 200, 200);
@@ -178,17 +213,15 @@ public class RatisConsensusTest {
 
   // FIXME: Turn on the test when it is stable
   public void transferLeader() throws Exception {
-    servers.get(0).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(1).createPeer(group.getGroupId(), group.getPeers());
-    servers.get(2).createPeer(group.getGroupId(), group.getPeers());
+    servers.get(0).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(1).createLocalPeer(group.getGroupId(), group.getPeers());
+    servers.get(2).createLocalPeer(group.getGroupId(), group.getPeers());
 
     doConsensus(servers.get(0), group.getGroupId(), 10, 10);
 
     int leaderIndex = servers.get(0).getLeader(group.getGroupId()).getNodeId() - 1;
 
-    ConsensusGenericResponse resp =
-        servers.get(0).transferLeader(group.getGroupId(), peers.get((leaderIndex + 1) % 3));
-    Assert.assertTrue(resp.isSuccess());
+    servers.get(0).transferLeader(group.getGroupId(), peers.get((leaderIndex + 1) % 3));
 
     Peer newLeader = servers.get(0).getLeader(group.getGroupId());
     Assert.assertNotNull(newLeader);
@@ -198,13 +231,13 @@ public class RatisConsensusTest {
 
   @Test
   public void transferSnapshot() throws Exception {
-    servers.get(0).createPeer(gid, peers.subList(0, 1));
+    servers.get(0).createLocalPeer(gid, peers.subList(0, 1));
 
     doConsensus(servers.get(0), gid, 10, 10);
-    Assert.assertTrue(servers.get(0).triggerSnapshot(gid).isSuccess());
+    servers.get(0).triggerSnapshot(gid);
 
-    servers.get(1).createPeer(gid, Collections.emptyList());
-    servers.get(0).addPeer(gid, peers.get(1));
+    servers.get(1).createLocalPeer(gid, peers.subList(1, 2));
+    servers.get(0).addRemotePeer(gid, peers.get(1));
 
     doConsensus(servers.get(1), gid, 10, 20);
   }
@@ -220,11 +253,15 @@ public class RatisConsensusTest {
           () -> {
             ByteBufferConsensusRequest incrReq = TestUtils.TestRequest.incrRequest();
 
-            ConsensusWriteResponse response = consensus.write(gid, incrReq);
-            if (response.getException() != null) {
-              response.getException().printStackTrace(System.out);
+            TSStatus response;
+            try {
+              response = consensus.write(gid, incrReq);
+            } catch (ConsensusException e) {
+              response = new TSStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
+              response.setMessage(e.getMessage());
+              e.printStackTrace(System.out);
             }
-            Assert.assertEquals(200, response.getStatus().getCode());
+            Assert.assertEquals(200, response.getCode());
             latch.countDown();
           });
     }
@@ -253,8 +290,7 @@ public class RatisConsensusTest {
     Assert.assertNotNull(leader);
 
     // Check we reached a consensus
-    ConsensusReadResponse response = leader.read(gid, getReq);
-    TestUtils.TestDataSet result = (TestUtils.TestDataSet) response.getDataset();
+    TestUtils.TestDataSet result = (TestUtils.TestDataSet) leader.read(gid, getReq);
     Assert.assertEquals(target, result.getNumber());
   }
 }
diff --git a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/RecoverReadTest.java b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/RecoverReadTest.java
index 001bb95de0a..b30b6fc5f58 100644
--- a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/RecoverReadTest.java
+++ b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/RecoverReadTest.java
@@ -20,10 +20,11 @@ package org.apache.iotdb.consensus.ratis;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.consensus.ConsensusGroupId;
+import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.common.request.IConsensusRequest;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
 import org.apache.iotdb.consensus.config.RatisConfig;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.consensus.exception.RatisUnderRecoveryException;
 
 import org.apache.ratis.util.TimeDuration;
@@ -123,7 +124,9 @@ public class RecoverReadTest {
     final ConsensusGroupId gid = miniCluster.getGid();
     final List<Peer> members = miniCluster.getPeers();
 
-    miniCluster.getServers().forEach(s -> s.createPeer(gid, members));
+    for (RatisConsensus s : miniCluster.getServers()) {
+      s.createLocalPeer(gid, members);
+    }
 
     // first write 10 ops
     TestUtils.write(miniCluster.getServer(0), gid, 10);
@@ -150,7 +153,9 @@ public class RecoverReadTest {
     final ConsensusGroupId gid = miniCluster.getGid();
     final List<Peer> members = miniCluster.getPeers();
 
-    miniCluster.getServers().forEach(s -> s.createPeer(gid, members));
+    for (RatisConsensus s : miniCluster.getServers()) {
+      s.createLocalPeer(gid, members);
+    }
 
     // first write 10 ops
     TestUtils.write(miniCluster.getServer(0), gid, 10);
@@ -171,20 +176,20 @@ public class RecoverReadTest {
 
     // try max 3 minutes
     final long startTs = System.currentTimeMillis();
-    ConsensusReadResponse resp = TestUtils.doRead(miniCluster.getServer(0), gid);
-    while (!resp.isSuccess()) {
+    DataSet resp;
+    try {
+      resp = TestUtils.doRead(miniCluster.getServer(0), gid);
+    } catch (ConsensusException e) {
       final long timeElapsed = System.currentTimeMillis() - startTs;
       if (timeElapsed > 1000 * 60 * 3) { // 3 min
-        Assert.fail(
-            "Linearizable read failed after 3 minutes, last exception seen: "
-                + resp.getException());
+        Assert.fail("Linearizable read failed after 3 minutes, last exception seen: " + e);
       }
       Thread.sleep(100);
-      logger.info("linearizable read failed  when restart, retrying: ", resp.getException());
+      logger.info("linearizable read failed  when restart, retrying: ", e);
       resp = TestUtils.doRead(miniCluster.getServer(0), gid);
     }
 
-    Assert.assertEquals(10, ((TestUtils.TestDataSet) resp.getDataset()).getNumber());
+    Assert.assertEquals(10, ((TestUtils.TestDataSet) resp).getNumber());
   }
 
   @Test
@@ -192,7 +197,9 @@ public class RecoverReadTest {
     final ConsensusGroupId gid = miniCluster.getGid();
     final List<Peer> members = miniCluster.getPeers();
 
-    miniCluster.getServers().forEach(s -> s.createPeer(gid, members));
+    for (RatisConsensus s : miniCluster.getServers()) {
+      s.createLocalPeer(gid, members);
+    }
 
     // first write 10 ops
     TestUtils.write(miniCluster.getServer(0), gid, 10);
@@ -209,8 +216,12 @@ public class RecoverReadTest {
     miniCluster.restart();
 
     // query during redo: get exception that ratis is under recovery
-    final ConsensusReadResponse readResponse = TestUtils.doRead(miniCluster.getServer(0), gid);
-    Assert.assertTrue(readResponse.getException() instanceof RatisUnderRecoveryException);
+    try {
+      TestUtils.doRead(miniCluster.getServer(0), gid);
+      Assert.fail();
+    } catch (ConsensusException e) {
+      Assert.assertTrue(e instanceof RatisUnderRecoveryException);
+    }
   }
 
   @Test
@@ -218,7 +229,9 @@ public class RecoverReadTest {
     final ConsensusGroupId gid = miniCluster.getGid();
     final List<Peer> members = miniCluster.getPeers();
 
-    miniCluster.getServers().forEach(s -> s.createPeer(gid, members));
+    for (RatisConsensus s : miniCluster.getServers()) {
+      s.createLocalPeer(gid, members);
+    }
 
     // first write 30 ops
     TestUtils.write(miniCluster.getServer(0), gid, 50);
@@ -238,7 +251,11 @@ public class RecoverReadTest {
     miniCluster.waitUntilActiveLeader();
 
     // query during redo: get exception that ratis is under recovery
-    final ConsensusReadResponse readResponse = TestUtils.doRead(miniCluster.getServer(0), gid);
-    Assert.assertTrue(readResponse.getException() instanceof RatisUnderRecoveryException);
+    try {
+      TestUtils.doRead(miniCluster.getServer(0), gid);
+      Assert.fail();
+    } catch (ConsensusException e) {
+      Assert.assertTrue(e instanceof RatisUnderRecoveryException);
+    }
   }
 }
diff --git a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/TestUtils.java b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/TestUtils.java
index 604d6afcec0..75e0426aa5e 100644
--- a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/TestUtils.java
+++ b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/ratis/TestUtils.java
@@ -33,8 +33,6 @@ import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.common.request.ByteBufferConsensusRequest;
 import org.apache.iotdb.consensus.common.request.IConsensusRequest;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
 import org.apache.iotdb.consensus.config.RatisConfig;
 import org.apache.iotdb.consensus.exception.ConsensusException;
@@ -379,24 +377,22 @@ public class TestUtils {
     }
   }
 
-  static void write(IConsensus consensus, ConsensusGroupId gid, int count) {
+  static void write(IConsensus consensus, ConsensusGroupId gid, int count)
+      throws ConsensusException {
     for (int i = 0; i < count; i++) {
       final ByteBufferConsensusRequest increment = TestRequest.incrRequest();
-      final ConsensusWriteResponse response = consensus.write(gid, increment);
-      Assert.assertEquals(200, response.getStatus().getCode());
+      final TSStatus response = consensus.write(gid, increment);
+      Assert.assertEquals(200, response.getCode());
     }
   }
 
   static int read(IConsensus consensus, ConsensusGroupId gid) throws ConsensusException {
-    final ConsensusReadResponse response = doRead(consensus, gid);
-    if (!response.isSuccess()) {
-      throw response.getException();
-    }
-    final TestUtils.TestDataSet result = (TestUtils.TestDataSet) response.getDataset();
+    final DataSet response = doRead(consensus, gid);
+    final TestUtils.TestDataSet result = (TestUtils.TestDataSet) response;
     return result.getNumber();
   }
 
-  static ConsensusReadResponse doRead(IConsensus consensus, ConsensusGroupId gid) {
+  static DataSet doRead(IConsensus consensus, ConsensusGroupId gid) throws ConsensusException {
     final ByteBufferConsensusRequest getReq = TestUtils.TestRequest.getRequest();
     return consensus.read(gid, getReq);
   }
diff --git a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/simple/RecoveryTest.java b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/simple/RecoveryTest.java
index b70499eb882..043e0055549 100644
--- a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/simple/RecoveryTest.java
+++ b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/simple/RecoveryTest.java
@@ -27,8 +27,8 @@ import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.consensus.EmptyStateMachine;
 import org.apache.iotdb.consensus.IConsensus;
 import org.apache.iotdb.consensus.common.Peer;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
 
 import org.apache.ratis.util.FileUtils;
@@ -78,7 +78,7 @@ public class RecoveryTest {
 
   @Test
   public void recoveryTest() throws Exception {
-    consensusImpl.createPeer(
+    consensusImpl.createLocalPeer(
         schemaRegionId,
         Collections.singletonList(new Peer(schemaRegionId, 1, new TEndPoint("0.0.0.0", 9000))));
 
@@ -86,14 +86,14 @@ public class RecoveryTest {
     consensusImpl = null;
 
     constructConsensus();
-
-    ConsensusGenericResponse response =
-        consensusImpl.createPeer(
-            schemaRegionId,
-            Collections.singletonList(new Peer(schemaRegionId, 1, new TEndPoint("0.0.0.0", 9000))));
-
-    Assert.assertEquals(
-        response.getException().getMessage(),
-        new ConsensusGroupAlreadyExistException(schemaRegionId).getMessage());
+    try {
+      consensusImpl.createLocalPeer(
+          schemaRegionId,
+          Collections.singletonList(new Peer(schemaRegionId, 1, new TEndPoint("0.0.0.0", 9000))));
+      Assert.fail();
+    } catch (ConsensusException e) {
+      Assert.assertEquals(
+          e.getMessage(), new ConsensusGroupAlreadyExistException(schemaRegionId).getMessage());
+    }
   }
 }
diff --git a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/simple/SimpleConsensusTest.java b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/simple/SimpleConsensusTest.java
index 6c065f76a4c..c69d564692d 100644
--- a/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/simple/SimpleConsensusTest.java
+++ b/iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/simple/SimpleConsensusTest.java
@@ -34,9 +34,8 @@ import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.common.request.ByteBufferConsensusRequest;
 import org.apache.iotdb.consensus.common.request.IConsensusRequest;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupNotExistException;
 import org.apache.iotdb.consensus.exception.IllegalPeerEndpointException;
@@ -44,6 +43,7 @@ import org.apache.iotdb.consensus.exception.IllegalPeerNumException;
 
 import org.apache.ratis.util.FileUtils;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -53,9 +53,7 @@ import java.util.Arrays;
 import java.util.Collections;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 public class SimpleConsensusTest {
@@ -166,144 +164,146 @@ public class SimpleConsensusTest {
 
   @Test
   public void addConsensusGroup() {
-    ConsensusGenericResponse response1 =
-        consensusImpl.createPeer(
-            dataRegionId,
-            Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
-    assertTrue(response1.isSuccess());
-    assertNull(response1.getException());
-
-    ConsensusGenericResponse response2 =
-        consensusImpl.createPeer(
-            dataRegionId,
-            Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
-    assertFalse(response2.isSuccess());
-    assertTrue(response2.getException() instanceof ConsensusGroupAlreadyExistException);
-
-    ConsensusGenericResponse response3 =
-        consensusImpl.createPeer(
-            dataRegionId,
-            Arrays.asList(
-                new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667)),
-                new Peer(dataRegionId, 1, new TEndPoint("0.0.0.1", 6667))));
-    assertFalse(response3.isSuccess());
-    assertTrue(response3.getException() instanceof IllegalPeerNumException);
-
-    ConsensusGenericResponse response4 =
-        consensusImpl.createPeer(
-            dataRegionId,
-            Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.1", 6667))));
-    assertFalse(response4.isSuccess());
-    assertTrue(response4.getException() instanceof IllegalPeerEndpointException);
-
-    ConsensusGenericResponse response5 =
-        consensusImpl.createPeer(
-            schemaRegionId,
-            Collections.singletonList(new Peer(schemaRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
-    assertTrue(response5.isSuccess());
-    assertNull(response5.getException());
+    try {
+      consensusImpl.createLocalPeer(
+          dataRegionId,
+          Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
+    } catch (ConsensusException e) {
+      Assert.fail();
+    }
+
+    try {
+      consensusImpl.createLocalPeer(
+          dataRegionId,
+          Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
+      Assert.fail();
+    } catch (ConsensusException e) {
+      assertTrue(e instanceof ConsensusGroupAlreadyExistException);
+    }
+
+    try {
+      consensusImpl.createLocalPeer(
+          dataRegionId,
+          Arrays.asList(
+              new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667)),
+              new Peer(dataRegionId, 1, new TEndPoint("0.0.0.1", 6667))));
+      Assert.fail();
+    } catch (ConsensusException e) {
+      assertTrue(e instanceof IllegalPeerNumException);
+    }
+
+    try {
+      consensusImpl.createLocalPeer(
+          dataRegionId,
+          Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.1", 6667))));
+      Assert.fail();
+    } catch (ConsensusException e) {
+      assertTrue(e instanceof IllegalPeerEndpointException);
+    }
+
+    try {
+      consensusImpl.createLocalPeer(
+          schemaRegionId,
+          Collections.singletonList(new Peer(schemaRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
+    } catch (ConsensusException e) {
+      Assert.fail();
+    }
   }
 
   @Test
-  public void removeConsensusGroup() {
-    ConsensusGenericResponse response1 = consensusImpl.deletePeer(dataRegionId);
-    assertFalse(response1.isSuccess());
-    assertTrue(response1.getException() instanceof ConsensusGroupNotExistException);
-
-    ConsensusGenericResponse response2 =
-        consensusImpl.createPeer(
-            dataRegionId,
-            Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
-    assertTrue(response2.isSuccess());
-    assertNull(response2.getException());
-
-    ConsensusGenericResponse response3 = consensusImpl.deletePeer(dataRegionId);
-    assertTrue(response3.isSuccess());
-    assertNull(response3.getException());
+  public void removeConsensusGroup() throws ConsensusException {
+    try {
+      consensusImpl.deleteLocalPeer(dataRegionId);
+      Assert.fail();
+    } catch (ConsensusException e) {
+      assertTrue(e instanceof ConsensusGroupNotExistException);
+    }
+
+    try {
+      consensusImpl.createLocalPeer(
+          dataRegionId,
+          Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
+      consensusImpl.deleteLocalPeer(dataRegionId);
+    } catch (ConsensusException e) {
+      Assert.fail();
+    }
   }
 
   @Test
   public void addPeer() {
-    ConsensusGenericResponse response =
-        consensusImpl.addPeer(
-            dataRegionId, new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667)));
-    assertFalse(response.isSuccess());
+    try {
+      consensusImpl.addRemotePeer(
+          dataRegionId, new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667)));
+      Assert.fail("Can't add peer in SimpleConsensus.");
+    } catch (ConsensusException e) {
+      // not handle
+    }
   }
 
   @Test
   public void removePeer() {
-    ConsensusGenericResponse response =
-        consensusImpl.removePeer(
-            dataRegionId, new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667)));
-    assertFalse(response.isSuccess());
-  }
-
-  @Test
-  public void changePeer() {
-    ConsensusGenericResponse response =
-        consensusImpl.changePeer(
-            dataRegionId,
-            Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
-    assertFalse(response.isSuccess());
+    try {
+      consensusImpl.removeRemotePeer(
+          dataRegionId, new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667)));
+      Assert.fail("Can't remove peer in SimpleConsensus.");
+    } catch (ConsensusException e) {
+      // not handle
+    }
   }
 
   @Test
   public void transferLeader() {
-    ConsensusGenericResponse response =
-        consensusImpl.transferLeader(
-            dataRegionId, new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667)));
-    assertFalse(response.isSuccess());
+    try {
+      consensusImpl.transferLeader(
+          dataRegionId, new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667)));
+      Assert.fail("Can't transfer leader in SimpleConsensus.");
+    } catch (ConsensusException e) {
+      // not handle
+    }
   }
 
   @Test
   public void triggerSnapshot() {
-    ConsensusGenericResponse response = consensusImpl.triggerSnapshot(dataRegionId);
-    assertFalse(response.isSuccess());
+    try {
+      consensusImpl.triggerSnapshot(dataRegionId);
+      Assert.fail("Can't trigger snapshot in SimpleConsensus.");
+    } catch (ConsensusException e) {
+      // not handle
+    }
   }
 
   @Test
-  public void write() {
-    ConsensusGenericResponse response1 =
-        consensusImpl.createPeer(
-            dataRegionId,
-            Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
-    assertTrue(response1.isSuccess());
-    assertNull(response1.getException());
-
-    ConsensusGenericResponse response2 =
-        consensusImpl.createPeer(
-            schemaRegionId,
-            Collections.singletonList(new Peer(schemaRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
-    assertTrue(response2.isSuccess());
-    assertNull(response2.getException());
-
-    ConsensusGenericResponse response3 =
-        consensusImpl.createPeer(
-            configId,
-            Collections.singletonList(new Peer(configId, 1, new TEndPoint("0.0.0.0", 6667))));
-    assertTrue(response3.isSuccess());
-    assertNull(response3.getException());
+  public void write() throws ConsensusException {
 
-    // test new TestStateMachine(true), should return 1;
-    ConsensusWriteResponse response4 = consensusImpl.write(dataRegionId, entry1);
-    assertNull(response4.getException());
-    assertNotNull(response4.getStatus());
-    assertEquals(-1, response4.getStatus().getCode());
+    consensusImpl.createLocalPeer(
+        dataRegionId,
+        Collections.singletonList(new Peer(dataRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
+
+    consensusImpl.createLocalPeer(
+        schemaRegionId,
+        Collections.singletonList(new Peer(schemaRegionId, 1, new TEndPoint("0.0.0.0", 6667))));
+
+    consensusImpl.createLocalPeer(
+        configId, Collections.singletonList(new Peer(configId, 1, new TEndPoint("0.0.0.0", 6667))));
 
     // test new TestStateMachine(false), should return -1;
-    ConsensusWriteResponse response5 = consensusImpl.write(schemaRegionId, entry1);
-    assertNull(response5.getException());
-    assertNotNull(response5.getStatus());
-    assertEquals(1, response5.getStatus().getCode());
+    TSStatus response4 = consensusImpl.write(dataRegionId, entry1);
+    assertNotNull(response4);
+    assertEquals(-1, response4.getCode());
+
+    // test new TestStateMachine(true), should return 1;
+    TSStatus response5 = consensusImpl.write(schemaRegionId, entry1);
+    assertNotNull(response5);
+    assertEquals(1, response5.getCode());
 
     // test new EmptyStateMachine(), should return 0;
-    ConsensusWriteResponse response6 = consensusImpl.write(configId, entry1);
-    assertNull(response6.getException());
-    assertEquals(0, response6.getStatus().getCode());
+    TSStatus response6 = consensusImpl.write(configId, entry1);
+    assertNotNull(response6);
+    assertEquals(0, response6.getCode());
 
     // test ByteBufferConsensusRequest, should return 0;
-    ConsensusWriteResponse response7 = consensusImpl.write(dataRegionId, entry2);
-    assertNull(response7.getException());
-    assertEquals(0, response7.getStatus().getCode());
+    TSStatus response7 = consensusImpl.write(dataRegionId, entry2);
+    assertNotNull(response7);
+    assertEquals(0, response7.getCode());
   }
 }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/DataRegionConsensusImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/DataRegionConsensusImpl.java
index c4eaf0f8bd8..b3b50a2216e 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/DataRegionConsensusImpl.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/DataRegionConsensusImpl.java
@@ -48,170 +48,157 @@ import java.util.concurrent.TimeUnit;
  */
 public class DataRegionConsensusImpl {
 
-  private static final IoTDBConfig conf = IoTDBDescriptor.getInstance().getConfig();
-
-  private static IConsensus INSTANCE = null;
-
   private DataRegionConsensusImpl() {
     // do nothing
   }
 
-  // need to create instance before calling this method
   public static IConsensus getInstance() {
-    return INSTANCE;
+    return DataRegionConsensusImplHolder.INSTANCE;
   }
 
-  public static synchronized IConsensus setupAndGetInstance() {
-    if (INSTANCE == null) {
-      INSTANCE =
-          ConsensusFactory.getConsensusImpl(
-                  conf.getDataRegionConsensusProtocolClass(),
-                  ConsensusConfig.newBuilder()
-                      .setThisNodeId(conf.getDataNodeId())
-                      .setThisNode(
-                          new TEndPoint(
-                              conf.getInternalAddress(), conf.getDataRegionConsensusPort()))
-                      .setStorageDir(conf.getDataRegionConsensusDir())
-                      .setConsensusGroupType(TConsensusGroupType.DataRegion)
-                      .setIoTConsensusConfig(
-                          IoTConsensusConfig.newBuilder()
-                              .setRpc(
-                                  RPC.newBuilder()
-                                      .setConnectionTimeoutInMs(conf.getConnectionTimeoutInMS())
-                                      .setRpcSelectorThreadNum(conf.getRpcSelectorThreadCount())
-                                      .setRpcMinConcurrentClientNum(
-                                          conf.getRpcMinConcurrentClientNum())
-                                      .setRpcMaxConcurrentClientNum(
-                                          conf.getRpcMaxConcurrentClientNum())
-                                      .setRpcThriftCompressionEnabled(
-                                          conf.isRpcThriftCompressionEnable())
-                                      .setSelectorNumOfClientManager(
-                                          conf.getSelectorNumOfClientManager())
-                                      .setThriftServerAwaitTimeForStopService(
-                                          conf.getThriftServerAwaitTimeForStopService())
-                                      .setThriftMaxFrameSize(conf.getThriftMaxFrameSize())
-                                      .setCoreClientNumForEachNode(
-                                          conf.getCoreClientNumForEachNode())
-                                      .setMaxClientNumForEachNode(conf.getMaxClientNumForEachNode())
-                                      .build())
-                              .setReplication(
-                                  IoTConsensusConfig.Replication.newBuilder()
-                                      .setWalThrottleThreshold(conf.getThrottleThreshold())
-                                      .setAllocateMemoryForConsensus(
-                                          conf.getAllocateMemoryForConsensus())
-                                      .setMaxLogEntriesNumPerBatch(
-                                          conf.getMaxLogEntriesNumPerBatch())
-                                      .setMaxSizePerBatch(conf.getMaxSizePerBatch())
-                                      .setMaxPendingBatchesNum(conf.getMaxPendingBatchesNum())
-                                      .setMaxMemoryRatioForQueue(conf.getMaxMemoryRatioForQueue())
-                                      .build())
-                              .build())
-                      .setRatisConfig(
-                          RatisConfig.newBuilder()
-                              // An empty log is committed after each restart, even if no data is
-                              // written. This setting ensures that compaction work is not discarded
-                              // even if there are frequent restarts
-                              .setSnapshot(
-                                  Snapshot.newBuilder()
-                                      .setCreationGap(1)
-                                      .setAutoTriggerThreshold(
-                                          conf.getDataRatisConsensusSnapshotTriggerThreshold())
-                                      .build())
-                              .setLog(
-                                  RatisConfig.Log.newBuilder()
-                                      .setUnsafeFlushEnabled(
-                                          conf.isDataRatisConsensusLogUnsafeFlushEnable())
-                                      .setForceSyncNum(conf.getDataRatisConsensusLogForceSyncNum())
-                                      .setSegmentSizeMax(
-                                          SizeInBytes.valueOf(
-                                              conf.getDataRatisConsensusLogSegmentSizeMax()))
-                                      .setPreserveNumsWhenPurge(
-                                          conf.getDataRatisConsensusPreserveWhenPurge())
-                                      .build())
-                              .setGrpc(
-                                  RatisConfig.Grpc.newBuilder()
-                                      .setFlowControlWindow(
-                                          SizeInBytes.valueOf(
-                                              conf.getDataRatisConsensusGrpcFlowControlWindow()))
-                                      .setLeaderOutstandingAppendsMax(
-                                          conf
-                                              .getDataRatisConsensusGrpcLeaderOutstandingAppendsMax())
-                                      .build())
-                              .setRpc(
-                                  RatisConfig.Rpc.newBuilder()
-                                      .setTimeoutMin(
-                                          TimeDuration.valueOf(
-                                              conf
-                                                  .getDataRatisConsensusLeaderElectionTimeoutMinMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .setTimeoutMax(
-                                          TimeDuration.valueOf(
-                                              conf
-                                                  .getDataRatisConsensusLeaderElectionTimeoutMaxMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .setRequestTimeout(
-                                          TimeDuration.valueOf(
-                                              conf.getDataRatisConsensusRequestTimeoutMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .setFirstElectionTimeoutMin(
-                                          TimeDuration.valueOf(
-                                              conf.getRatisFirstElectionTimeoutMinMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .setFirstElectionTimeoutMax(
-                                          TimeDuration.valueOf(
-                                              conf.getRatisFirstElectionTimeoutMaxMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .build())
-                              .setClient(
-                                  RatisConfig.Client.newBuilder()
-                                      .setClientRequestTimeoutMillis(
-                                          conf.getDataRatisConsensusRequestTimeoutMs())
-                                      .setClientMaxRetryAttempt(
-                                          conf.getDataRatisConsensusMaxRetryAttempts())
-                                      .setClientRetryInitialSleepTimeMs(
-                                          conf.getDataRatisConsensusInitialSleepTimeMs())
-                                      .setClientRetryMaxSleepTimeMs(
-                                          conf.getDataRatisConsensusMaxSleepTimeMs())
-                                      .setCoreClientNumForEachNode(
-                                          conf.getCoreClientNumForEachNode())
-                                      .setMaxClientNumForEachNode(conf.getMaxClientNumForEachNode())
-                                      .build())
-                              .setImpl(
-                                  RatisConfig.Impl.newBuilder()
-                                      .setTriggerSnapshotFileSize(conf.getDataRatisLogMax())
-                                      .build())
-                              .setLeaderLogAppender(
-                                  RatisConfig.LeaderLogAppender.newBuilder()
-                                      .setBufferByteLimit(
-                                          conf.getDataRatisConsensusLogAppenderBufferSizeMax())
-                                      .build())
-                              .setRead(
-                                  RatisConfig.Read.newBuilder()
-                                      // use thrift connection timeout to unify read timeout
-                                      .setReadTimeout(
-                                          TimeDuration.valueOf(
-                                              conf.getConnectionTimeoutInMS(),
-                                              TimeUnit.MILLISECONDS))
-                                      .build())
-                              .build())
-                      .build(),
-                  DataRegionConsensusImpl::createDataRegionStateMachine)
-              .orElseThrow(
-                  () ->
-                      new IllegalArgumentException(
-                          String.format(
-                              ConsensusFactory.CONSTRUCT_FAILED_MSG,
-                              conf.getDataRegionConsensusProtocolClass())));
-    }
-    return INSTANCE;
-  }
+  private static class DataRegionConsensusImplHolder {
+
+    private static final IoTDBConfig CONF = IoTDBDescriptor.getInstance().getConfig();
+
+    private static final IConsensus INSTANCE =
+        ConsensusFactory.getConsensusImpl(
+                CONF.getDataRegionConsensusProtocolClass(),
+                ConsensusConfig.newBuilder()
+                    .setThisNodeId(CONF.getDataNodeId())
+                    .setThisNode(
+                        new TEndPoint(CONF.getInternalAddress(), CONF.getDataRegionConsensusPort()))
+                    .setStorageDir(CONF.getDataRegionConsensusDir())
+                    .setConsensusGroupType(TConsensusGroupType.DataRegion)
+                    .setIoTConsensusConfig(
+                        IoTConsensusConfig.newBuilder()
+                            .setRpc(
+                                RPC.newBuilder()
+                                    .setConnectionTimeoutInMs(CONF.getConnectionTimeoutInMS())
+                                    .setRpcSelectorThreadNum(CONF.getRpcSelectorThreadCount())
+                                    .setRpcMinConcurrentClientNum(
+                                        CONF.getRpcMinConcurrentClientNum())
+                                    .setRpcMaxConcurrentClientNum(
+                                        CONF.getRpcMaxConcurrentClientNum())
+                                    .setRpcThriftCompressionEnabled(
+                                        CONF.isRpcThriftCompressionEnable())
+                                    .setSelectorNumOfClientManager(
+                                        CONF.getSelectorNumOfClientManager())
+                                    .setThriftServerAwaitTimeForStopService(
+                                        CONF.getThriftServerAwaitTimeForStopService())
+                                    .setThriftMaxFrameSize(CONF.getThriftMaxFrameSize())
+                                    .setCoreClientNumForEachNode(CONF.getCoreClientNumForEachNode())
+                                    .setMaxClientNumForEachNode(CONF.getMaxClientNumForEachNode())
+                                    .build())
+                            .setReplication(
+                                IoTConsensusConfig.Replication.newBuilder()
+                                    .setWalThrottleThreshold(CONF.getThrottleThreshold())
+                                    .setAllocateMemoryForConsensus(
+                                        CONF.getAllocateMemoryForConsensus())
+                                    .setMaxLogEntriesNumPerBatch(CONF.getMaxLogEntriesNumPerBatch())
+                                    .setMaxSizePerBatch(CONF.getMaxSizePerBatch())
+                                    .setMaxPendingBatchesNum(CONF.getMaxPendingBatchesNum())
+                                    .setMaxMemoryRatioForQueue(CONF.getMaxMemoryRatioForQueue())
+                                    .build())
+                            .build())
+                    .setRatisConfig(
+                        RatisConfig.newBuilder()
+                            // An empty log is committed after each restart, even if no data is
+                            // written. This setting ensures that compaction work is not discarded
+                            // even if there are frequent restarts
+                            .setSnapshot(
+                                Snapshot.newBuilder()
+                                    .setCreationGap(1)
+                                    .setAutoTriggerThreshold(
+                                        CONF.getDataRatisConsensusSnapshotTriggerThreshold())
+                                    .build())
+                            .setLog(
+                                RatisConfig.Log.newBuilder()
+                                    .setUnsafeFlushEnabled(
+                                        CONF.isDataRatisConsensusLogUnsafeFlushEnable())
+                                    .setForceSyncNum(CONF.getDataRatisConsensusLogForceSyncNum())
+                                    .setSegmentSizeMax(
+                                        SizeInBytes.valueOf(
+                                            CONF.getDataRatisConsensusLogSegmentSizeMax()))
+                                    .setPreserveNumsWhenPurge(
+                                        CONF.getDataRatisConsensusPreserveWhenPurge())
+                                    .build())
+                            .setGrpc(
+                                RatisConfig.Grpc.newBuilder()
+                                    .setFlowControlWindow(
+                                        SizeInBytes.valueOf(
+                                            CONF.getDataRatisConsensusGrpcFlowControlWindow()))
+                                    .setLeaderOutstandingAppendsMax(
+                                        CONF.getDataRatisConsensusGrpcLeaderOutstandingAppendsMax())
+                                    .build())
+                            .setRpc(
+                                RatisConfig.Rpc.newBuilder()
+                                    .setTimeoutMin(
+                                        TimeDuration.valueOf(
+                                            CONF.getDataRatisConsensusLeaderElectionTimeoutMinMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .setTimeoutMax(
+                                        TimeDuration.valueOf(
+                                            CONF.getDataRatisConsensusLeaderElectionTimeoutMaxMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .setRequestTimeout(
+                                        TimeDuration.valueOf(
+                                            CONF.getDataRatisConsensusRequestTimeoutMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .setFirstElectionTimeoutMin(
+                                        TimeDuration.valueOf(
+                                            CONF.getRatisFirstElectionTimeoutMinMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .setFirstElectionTimeoutMax(
+                                        TimeDuration.valueOf(
+                                            CONF.getRatisFirstElectionTimeoutMaxMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .build())
+                            .setClient(
+                                RatisConfig.Client.newBuilder()
+                                    .setClientRequestTimeoutMillis(
+                                        CONF.getDataRatisConsensusRequestTimeoutMs())
+                                    .setClientMaxRetryAttempt(
+                                        CONF.getDataRatisConsensusMaxRetryAttempts())
+                                    .setClientRetryInitialSleepTimeMs(
+                                        CONF.getDataRatisConsensusInitialSleepTimeMs())
+                                    .setClientRetryMaxSleepTimeMs(
+                                        CONF.getDataRatisConsensusMaxSleepTimeMs())
+                                    .setCoreClientNumForEachNode(CONF.getCoreClientNumForEachNode())
+                                    .setMaxClientNumForEachNode(CONF.getMaxClientNumForEachNode())
+                                    .build())
+                            .setImpl(
+                                RatisConfig.Impl.newBuilder()
+                                    .setTriggerSnapshotFileSize(CONF.getDataRatisLogMax())
+                                    .build())
+                            .setLeaderLogAppender(
+                                RatisConfig.LeaderLogAppender.newBuilder()
+                                    .setBufferByteLimit(
+                                        CONF.getDataRatisConsensusLogAppenderBufferSizeMax())
+                                    .build())
+                            .setRead(
+                                RatisConfig.Read.newBuilder()
+                                    // use thrift connection timeout to unify read timeout
+                                    .setReadTimeout(
+                                        TimeDuration.valueOf(
+                                            CONF.getConnectionTimeoutInMS(), TimeUnit.MILLISECONDS))
+                                    .build())
+                            .build())
+                    .build(),
+                DataRegionConsensusImplHolder::createDataRegionStateMachine)
+            .orElseThrow(
+                () ->
+                    new IllegalArgumentException(
+                        String.format(
+                            ConsensusFactory.CONSTRUCT_FAILED_MSG,
+                            CONF.getDataRegionConsensusProtocolClass())));
 
-  private static DataRegionStateMachine createDataRegionStateMachine(ConsensusGroupId gid) {
-    DataRegion dataRegion = StorageEngine.getInstance().getDataRegion((DataRegionId) gid);
-    if (ConsensusFactory.IOT_CONSENSUS.equals(conf.getDataRegionConsensusProtocolClass())) {
-      return new IoTConsensusDataRegionStateMachine(dataRegion);
-    } else {
-      return new DataRegionStateMachine(dataRegion);
+    private static DataRegionStateMachine createDataRegionStateMachine(ConsensusGroupId gid) {
+      DataRegion dataRegion = StorageEngine.getInstance().getDataRegion((DataRegionId) gid);
+      if (ConsensusFactory.IOT_CONSENSUS.equals(CONF.getDataRegionConsensusProtocolClass())) {
+        return new IoTConsensusDataRegionStateMachine(dataRegion);
+      } else {
+        return new DataRegionStateMachine(dataRegion);
+      }
     }
   }
 }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/SchemaRegionConsensusImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/SchemaRegionConsensusImpl.java
index 352c76adf95..ca1b8a564e8 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/SchemaRegionConsensusImpl.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/SchemaRegionConsensusImpl.java
@@ -42,120 +42,114 @@ import java.util.concurrent.TimeUnit;
  */
 public class SchemaRegionConsensusImpl {
 
-  private static final IoTDBConfig conf = IoTDBDescriptor.getInstance().getConfig();
-
-  private static IConsensus INSTANCE = null;
-
-  private SchemaRegionConsensusImpl() {}
+  private SchemaRegionConsensusImpl() {
+    // do nothing
+  }
 
-  // need to create instance before calling this method
   public static IConsensus getInstance() {
-    return INSTANCE;
+    return SchemaRegionConsensusImplHolder.INSTANCE;
   }
 
-  public static synchronized IConsensus setupAndGetInstance() {
-    if (INSTANCE == null) {
-      INSTANCE =
-          ConsensusFactory.getConsensusImpl(
-                  conf.getSchemaRegionConsensusProtocolClass(),
-                  ConsensusConfig.newBuilder()
-                      .setThisNodeId(conf.getDataNodeId())
-                      .setThisNode(
-                          new TEndPoint(
-                              conf.getInternalAddress(), conf.getSchemaRegionConsensusPort()))
-                      .setConsensusGroupType(TConsensusGroupType.SchemaRegion)
-                      .setRatisConfig(
-                          RatisConfig.newBuilder()
-                              .setSnapshot(
-                                  RatisConfig.Snapshot.newBuilder()
-                                      .setAutoTriggerThreshold(
-                                          conf.getSchemaRatisConsensusSnapshotTriggerThreshold())
-                                      .build())
-                              .setLog(
-                                  RatisConfig.Log.newBuilder()
-                                      .setUnsafeFlushEnabled(
-                                          conf.isSchemaRatisConsensusLogUnsafeFlushEnable())
-                                      .setSegmentSizeMax(
-                                          SizeInBytes.valueOf(
-                                              conf.getSchemaRatisConsensusLogSegmentSizeMax()))
-                                      .setPreserveNumsWhenPurge(
-                                          conf.getSchemaRatisConsensusPreserveWhenPurge())
-                                      .build())
-                              .setGrpc(
-                                  RatisConfig.Grpc.newBuilder()
-                                      .setFlowControlWindow(
-                                          SizeInBytes.valueOf(
-                                              conf.getSchemaRatisConsensusGrpcFlowControlWindow()))
-                                      .build())
-                              .setRpc(
-                                  RatisConfig.Rpc.newBuilder()
-                                      .setTimeoutMin(
-                                          TimeDuration.valueOf(
-                                              conf
-                                                  .getSchemaRatisConsensusLeaderElectionTimeoutMinMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .setTimeoutMax(
-                                          TimeDuration.valueOf(
-                                              conf
-                                                  .getSchemaRatisConsensusLeaderElectionTimeoutMaxMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .setRequestTimeout(
-                                          TimeDuration.valueOf(
-                                              conf.getSchemaRatisConsensusRequestTimeoutMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .setFirstElectionTimeoutMin(
-                                          TimeDuration.valueOf(
-                                              conf.getRatisFirstElectionTimeoutMinMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .setFirstElectionTimeoutMax(
-                                          TimeDuration.valueOf(
-                                              conf.getRatisFirstElectionTimeoutMaxMs(),
-                                              TimeUnit.MILLISECONDS))
-                                      .build())
-                              .setClient(
-                                  RatisConfig.Client.newBuilder()
-                                      .setClientRequestTimeoutMillis(
-                                          conf.getDataRatisConsensusRequestTimeoutMs())
-                                      .setClientMaxRetryAttempt(
-                                          conf.getDataRatisConsensusMaxRetryAttempts())
-                                      .setClientRetryInitialSleepTimeMs(
-                                          conf.getDataRatisConsensusInitialSleepTimeMs())
-                                      .setClientRetryMaxSleepTimeMs(
-                                          conf.getDataRatisConsensusMaxSleepTimeMs())
-                                      .setCoreClientNumForEachNode(
-                                          conf.getCoreClientNumForEachNode())
-                                      .setMaxClientNumForEachNode(conf.getMaxClientNumForEachNode())
-                                      .build())
-                              .setImpl(
-                                  RatisConfig.Impl.newBuilder()
-                                      .setTriggerSnapshotFileSize(conf.getSchemaRatisLogMax())
-                                      .build())
-                              .setLeaderLogAppender(
-                                  RatisConfig.LeaderLogAppender.newBuilder()
-                                      .setBufferByteLimit(
-                                          conf.getSchemaRatisConsensusLogAppenderBufferSizeMax())
-                                      .build())
-                              .setRead(
-                                  RatisConfig.Read.newBuilder()
-                                      // use thrift connection timeout to unify read timeout
-                                      .setReadTimeout(
-                                          TimeDuration.valueOf(
-                                              conf.getConnectionTimeoutInMS(),
-                                              TimeUnit.MILLISECONDS))
-                                      .build())
-                              .build())
-                      .setStorageDir(conf.getSchemaRegionConsensusDir())
-                      .build(),
-                  gid ->
-                      new SchemaRegionStateMachine(
-                          SchemaEngine.getInstance().getSchemaRegion((SchemaRegionId) gid)))
-              .orElseThrow(
-                  () ->
-                      new IllegalArgumentException(
-                          String.format(
-                              ConsensusFactory.CONSTRUCT_FAILED_MSG,
-                              conf.getSchemaRegionConsensusProtocolClass())));
-    }
-    return INSTANCE;
+  private static class SchemaRegionConsensusImplHolder {
+
+    private static final IoTDBConfig CONF = IoTDBDescriptor.getInstance().getConfig();
+    private static final IConsensus INSTANCE =
+        ConsensusFactory.getConsensusImpl(
+                CONF.getSchemaRegionConsensusProtocolClass(),
+                ConsensusConfig.newBuilder()
+                    .setThisNodeId(CONF.getDataNodeId())
+                    .setThisNode(
+                        new TEndPoint(
+                            CONF.getInternalAddress(), CONF.getSchemaRegionConsensusPort()))
+                    .setConsensusGroupType(TConsensusGroupType.SchemaRegion)
+                    .setRatisConfig(
+                        RatisConfig.newBuilder()
+                            .setSnapshot(
+                                RatisConfig.Snapshot.newBuilder()
+                                    .setAutoTriggerThreshold(
+                                        CONF.getSchemaRatisConsensusSnapshotTriggerThreshold())
+                                    .build())
+                            .setLog(
+                                RatisConfig.Log.newBuilder()
+                                    .setUnsafeFlushEnabled(
+                                        CONF.isSchemaRatisConsensusLogUnsafeFlushEnable())
+                                    .setSegmentSizeMax(
+                                        SizeInBytes.valueOf(
+                                            CONF.getSchemaRatisConsensusLogSegmentSizeMax()))
+                                    .setPreserveNumsWhenPurge(
+                                        CONF.getSchemaRatisConsensusPreserveWhenPurge())
+                                    .build())
+                            .setGrpc(
+                                RatisConfig.Grpc.newBuilder()
+                                    .setFlowControlWindow(
+                                        SizeInBytes.valueOf(
+                                            CONF.getSchemaRatisConsensusGrpcFlowControlWindow()))
+                                    .build())
+                            .setRpc(
+                                RatisConfig.Rpc.newBuilder()
+                                    .setTimeoutMin(
+                                        TimeDuration.valueOf(
+                                            CONF
+                                                .getSchemaRatisConsensusLeaderElectionTimeoutMinMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .setTimeoutMax(
+                                        TimeDuration.valueOf(
+                                            CONF
+                                                .getSchemaRatisConsensusLeaderElectionTimeoutMaxMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .setRequestTimeout(
+                                        TimeDuration.valueOf(
+                                            CONF.getSchemaRatisConsensusRequestTimeoutMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .setFirstElectionTimeoutMin(
+                                        TimeDuration.valueOf(
+                                            CONF.getRatisFirstElectionTimeoutMinMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .setFirstElectionTimeoutMax(
+                                        TimeDuration.valueOf(
+                                            CONF.getRatisFirstElectionTimeoutMaxMs(),
+                                            TimeUnit.MILLISECONDS))
+                                    .build())
+                            .setClient(
+                                RatisConfig.Client.newBuilder()
+                                    .setClientRequestTimeoutMillis(
+                                        CONF.getDataRatisConsensusRequestTimeoutMs())
+                                    .setClientMaxRetryAttempt(
+                                        CONF.getDataRatisConsensusMaxRetryAttempts())
+                                    .setClientRetryInitialSleepTimeMs(
+                                        CONF.getDataRatisConsensusInitialSleepTimeMs())
+                                    .setClientRetryMaxSleepTimeMs(
+                                        CONF.getDataRatisConsensusMaxSleepTimeMs())
+                                    .setCoreClientNumForEachNode(CONF.getCoreClientNumForEachNode())
+                                    .setMaxClientNumForEachNode(CONF.getMaxClientNumForEachNode())
+                                    .build())
+                            .setImpl(
+                                RatisConfig.Impl.newBuilder()
+                                    .setTriggerSnapshotFileSize(CONF.getSchemaRatisLogMax())
+                                    .build())
+                            .setLeaderLogAppender(
+                                RatisConfig.LeaderLogAppender.newBuilder()
+                                    .setBufferByteLimit(
+                                        CONF.getSchemaRatisConsensusLogAppenderBufferSizeMax())
+                                    .build())
+                            .setRead(
+                                RatisConfig.Read.newBuilder()
+                                    // use thrift connection timeout to unify read timeout
+                                    .setReadTimeout(
+                                        TimeDuration.valueOf(
+                                            CONF.getConnectionTimeoutInMS(), TimeUnit.MILLISECONDS))
+                                    .build())
+                            .build())
+                    .setStorageDir(CONF.getSchemaRegionConsensusDir())
+                    .build(),
+                gid ->
+                    new SchemaRegionStateMachine(
+                        SchemaEngine.getInstance().getSchemaRegion((SchemaRegionId) gid)))
+            .orElseThrow(
+                () ->
+                    new IllegalArgumentException(
+                        String.format(
+                            ConsensusFactory.CONSTRUCT_FAILED_MSG,
+                            CONF.getSchemaRegionConsensusProtocolClass())));
   }
 }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
index 2cf8ce76e1d..d9390ab1976 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/ConfigNodeClient.java
@@ -159,7 +159,7 @@ public class ConfigNodeClient implements IConfigNodeRPCService.Iface, ThriftClie
 
   private static final String MSG_RECONNECTION_DATANODE_FAIL =
       "Failed to connect to ConfigNode %s from DataNode %s when executing %s, Exception:";
-  private static final int RETRY_INTERVAL_MS = 1000;
+  private static final int RETRY_INTERVAL_MS = 2000;
 
   private final ThriftClientProperty property;
 
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
index 446f71e2cb3..ce5cbe6d15c 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
@@ -50,7 +50,7 @@ import org.apache.iotdb.commons.trigger.TriggerInformation;
 import org.apache.iotdb.commons.udf.UDFInformation;
 import org.apache.iotdb.commons.udf.service.UDFManagementService;
 import org.apache.iotdb.consensus.common.Peer;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupNotExistException;
 import org.apache.iotdb.db.auth.AuthorizerManager;
@@ -1223,25 +1223,22 @@ public class DataNodeInternalRPCServiceImpl implements IDataNodeRPCService.Iface
 
   private Map<TConsensusGroupId, Boolean> getJudgedLeaders() {
     Map<TConsensusGroupId, Boolean> result = new HashMap<>();
-    if (DataRegionConsensusImpl.getInstance() != null) {
-      DataRegionConsensusImpl.getInstance()
-          .getAllConsensusGroupIds()
-          .forEach(
-              groupId ->
-                  result.put(
-                      groupId.convertToTConsensusGroupId(),
-                      DataRegionConsensusImpl.getInstance().isLeader(groupId)));
-    }
+    DataRegionConsensusImpl.getInstance()
+        .getAllConsensusGroupIds()
+        .forEach(
+            groupId ->
+                result.put(
+                    groupId.convertToTConsensusGroupId(),
+                    DataRegionConsensusImpl.getInstance().isLeader(groupId)));
+
+    SchemaRegionConsensusImpl.getInstance()
+        .getAllConsensusGroupIds()
+        .forEach(
+            groupId ->
+                result.put(
+                    groupId.convertToTConsensusGroupId(),
+                    SchemaRegionConsensusImpl.getInstance().isLeader(groupId)));
 
-    if (SchemaRegionConsensusImpl.getInstance() != null) {
-      SchemaRegionConsensusImpl.getInstance()
-          .getAllConsensusGroupIds()
-          .forEach(
-              groupId ->
-                  result.put(
-                      groupId.convertToTConsensusGroupId(),
-                      SchemaRegionConsensusImpl.getInstance().isLeader(groupId)));
-    }
     return result;
   }
 
@@ -1442,21 +1439,21 @@ public class DataNodeInternalRPCServiceImpl implements IDataNodeRPCService.Iface
     ConsensusGroupId consensusGroupId =
         ConsensusGroupId.Factory.createFromTConsensusGroupId(tconsensusGroupId);
     if (consensusGroupId instanceof DataRegionId) {
-      ConsensusGenericResponse response =
-          DataRegionConsensusImpl.getInstance().deletePeer(consensusGroupId);
-      if (!response.isSuccess()
-          && !(response.getException() instanceof ConsensusGroupNotExistException)) {
-        return RpcUtils.getStatus(
-            TSStatusCode.DELETE_REGION_ERROR, response.getException().getMessage());
+      try {
+        DataRegionConsensusImpl.getInstance().deleteLocalPeer(consensusGroupId);
+      } catch (ConsensusException e) {
+        if (!(e instanceof ConsensusGroupNotExistException)) {
+          return RpcUtils.getStatus(TSStatusCode.DELETE_REGION_ERROR, e.getMessage());
+        }
       }
       return regionManager.deleteDataRegion((DataRegionId) consensusGroupId);
     } else {
-      ConsensusGenericResponse response =
-          SchemaRegionConsensusImpl.getInstance().deletePeer(consensusGroupId);
-      if (!response.isSuccess()
-          && !(response.getException() instanceof ConsensusGroupNotExistException)) {
-        return RpcUtils.getStatus(
-            TSStatusCode.DELETE_REGION_ERROR, response.getException().getMessage());
+      try {
+        SchemaRegionConsensusImpl.getInstance().deleteLocalPeer(consensusGroupId);
+      } catch (ConsensusException e) {
+        if (!(e instanceof ConsensusGroupNotExistException)) {
+          return RpcUtils.getStatus(TSStatusCode.DELETE_REGION_ERROR, e.getMessage());
+        }
       }
       return regionManager.deleteSchemaRegion((SchemaRegionId) consensusGroupId);
     }
@@ -1491,26 +1488,24 @@ public class DataNodeInternalRPCServiceImpl implements IDataNodeRPCService.Iface
 
   private TSStatus transferLeader(ConsensusGroupId regionId, Peer newLeaderPeer) {
     TSStatus status = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
-    ConsensusGenericResponse resp;
-    if (regionId instanceof DataRegionId) {
-      resp = DataRegionConsensusImpl.getInstance().transferLeader(regionId, newLeaderPeer);
-    } else if (regionId instanceof SchemaRegionId) {
-      resp = SchemaRegionConsensusImpl.getInstance().transferLeader(regionId, newLeaderPeer);
-    } else {
-      status.setCode(TSStatusCode.REGION_LEADER_CHANGE_ERROR.getStatusCode());
-      status.setMessage("[ChangeRegionLeader] Error Region type: " + regionId);
-      return status;
-    }
-
-    if (!resp.isSuccess()) {
+    try {
+      if (regionId instanceof DataRegionId) {
+        DataRegionConsensusImpl.getInstance().transferLeader(regionId, newLeaderPeer);
+      } else if (regionId instanceof SchemaRegionId) {
+        SchemaRegionConsensusImpl.getInstance().transferLeader(regionId, newLeaderPeer);
+      } else {
+        status.setCode(TSStatusCode.REGION_LEADER_CHANGE_ERROR.getStatusCode());
+        status.setMessage("[ChangeRegionLeader] Error Region type: " + regionId);
+        return status;
+      }
+    } catch (ConsensusException e) {
       LOGGER.warn(
-          "[ChangeRegionLeader] Failed to change the leader of RegionGroup: {}",
-          regionId,
-          resp.getException());
+          "[ChangeRegionLeader] Failed to change the leader of RegionGroup: {}", regionId, e);
       status.setCode(TSStatusCode.REGION_LEADER_CHANGE_ERROR.getStatusCode());
-      status.setMessage(resp.getException().getMessage());
+      status.setMessage(e.getMessage());
       return status;
     }
+
     status.setMessage(
         "[ChangeRegionLeader] Successfully change the leader of RegionGroup: "
             + regionId
@@ -1781,23 +1776,24 @@ public class DataNodeInternalRPCServiceImpl implements IDataNodeRPCService.Iface
         peers,
         regionId);
     TSStatus status = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
-    ConsensusGenericResponse resp;
-    if (regionId instanceof DataRegionId) {
-      resp = DataRegionConsensusImpl.getInstance().createPeer(regionId, peers);
-    } else {
-      resp = SchemaRegionConsensusImpl.getInstance().createPeer(regionId, peers);
-    }
-    if (!resp.isSuccess()
-        && !(resp.getException() instanceof ConsensusGroupAlreadyExistException)) {
-      LOGGER.warn(
-          "{}, CreateNewRegionPeer error, peers: {}, regionId: {}, errorMessage",
-          REGION_MIGRATE_PROCESS,
-          peers,
-          regionId,
-          resp.getException());
-      status.setCode(TSStatusCode.MIGRATE_REGION_ERROR.getStatusCode());
-      status.setMessage(resp.getException().getMessage());
-      return status;
+    try {
+      if (regionId instanceof DataRegionId) {
+        DataRegionConsensusImpl.getInstance().createLocalPeer(regionId, peers);
+      } else {
+        SchemaRegionConsensusImpl.getInstance().createLocalPeer(regionId, peers);
+      }
+    } catch (ConsensusException e) {
+      if (!(e instanceof ConsensusGroupAlreadyExistException)) {
+        LOGGER.warn(
+            "{}, CreateNewRegionPeer error, peers: {}, regionId: {}, errorMessage",
+            REGION_MIGRATE_PROCESS,
+            peers,
+            regionId,
+            e);
+        status.setCode(TSStatusCode.MIGRATE_REGION_ERROR.getStatusCode());
+        status.setMessage(e.getMessage());
+        return status;
+      }
     }
     LOGGER.info(
         "{}, Succeed to createNewRegionPeer {} for region {}",
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeRegionManager.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeRegionManager.java
index 55c4e3bb87d..530ce68e997 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeRegionManager.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeRegionManager.java
@@ -31,7 +31,7 @@ import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.consensus.common.Peer;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
 import org.apache.iotdb.db.consensus.DataRegionConsensusImpl;
 import org.apache.iotdb.db.consensus.SchemaRegionConsensusImpl;
@@ -105,9 +105,9 @@ public class DataNodeRegionManager {
 
   public TSStatus createSchemaRegion(TRegionReplicaSet regionReplicaSet, String storageGroup) {
     TSStatus tsStatus;
+    SchemaRegionId schemaRegionId = new SchemaRegionId(regionReplicaSet.getRegionId().getId());
     try {
       PartialPath storageGroupPartitionPath = new PartialPath(storageGroup);
-      SchemaRegionId schemaRegionId = new SchemaRegionId(regionReplicaSet.getRegionId().getId());
       schemaEngine.createSchemaRegion(storageGroupPartitionPath, schemaRegionId);
       schemaRegionLockMap.put(schemaRegionId, new ReentrantReadWriteLock(false));
       List<Peer> peers = new ArrayList<>();
@@ -118,19 +118,8 @@ public class DataNodeRegionManager {
                 dataNodeLocation.getSchemaRegionConsensusEndPoint().getPort());
         peers.add(new Peer(schemaRegionId, dataNodeLocation.getDataNodeId(), endpoint));
       }
-      ConsensusGenericResponse consensusGenericResponse =
-          SchemaRegionConsensusImpl.getInstance().createPeer(schemaRegionId, peers);
-      if (consensusGenericResponse.isSuccess()) {
-        tsStatus = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
-      } else if (consensusGenericResponse.getException()
-          instanceof ConsensusGroupAlreadyExistException) {
-        tsStatus = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
-        tsStatus.setMessage(
-            String.format("SchemaRegion %d already exists.", schemaRegionId.getId()));
-      } else {
-        tsStatus = new TSStatus(TSStatusCode.CREATE_REGION_ERROR.getStatusCode());
-        tsStatus.setMessage(consensusGenericResponse.getException().getMessage());
-      }
+      SchemaRegionConsensusImpl.getInstance().createLocalPeer(schemaRegionId, peers);
+      tsStatus = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
     } catch (IllegalPathException e1) {
       LOGGER.error("Create Schema Region {} failed because path is illegal.", storageGroup);
       tsStatus = new TSStatus(TSStatusCode.ILLEGAL_PATH.getStatusCode());
@@ -140,6 +129,12 @@ public class DataNodeRegionManager {
       tsStatus = new TSStatus(TSStatusCode.CREATE_REGION_ERROR.getStatusCode());
       tsStatus.setMessage(
           String.format("Create Schema Region failed because of %s", e2.getMessage()));
+    } catch (ConsensusGroupAlreadyExistException e) {
+      tsStatus = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
+      tsStatus.setMessage(String.format("SchemaRegion %d already exists.", schemaRegionId.getId()));
+    } catch (ConsensusException e) {
+      tsStatus = new TSStatus(TSStatusCode.CREATE_REGION_ERROR.getStatusCode());
+      tsStatus.setMessage(e.getMessage());
     }
     return tsStatus;
   }
@@ -147,8 +142,8 @@ public class DataNodeRegionManager {
   public TSStatus createDataRegion(
       TRegionReplicaSet regionReplicaSet, String storageGroup, long ttl) {
     TSStatus tsStatus;
+    DataRegionId dataRegionId = new DataRegionId(regionReplicaSet.getRegionId().getId());
     try {
-      DataRegionId dataRegionId = new DataRegionId(regionReplicaSet.getRegionId().getId());
       storageEngine.createDataRegion(dataRegionId, storageGroup, ttl);
       dataRegionLockMap.put(dataRegionId, new ReentrantReadWriteLock(false));
       List<Peer> peers = new ArrayList<>();
@@ -159,22 +154,18 @@ public class DataNodeRegionManager {
                 dataNodeLocation.getDataRegionConsensusEndPoint().getPort());
         peers.add(new Peer(dataRegionId, dataNodeLocation.getDataNodeId(), endpoint));
       }
-      ConsensusGenericResponse consensusGenericResponse =
-          DataRegionConsensusImpl.getInstance().createPeer(dataRegionId, peers);
-      if (consensusGenericResponse.isSuccess()) {
-        tsStatus = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
-      } else if (consensusGenericResponse.getException()
-          instanceof ConsensusGroupAlreadyExistException) {
-        tsStatus = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
-        tsStatus.setMessage(String.format("DataRegion %d already exists.", dataRegionId.getId()));
-      } else {
-        tsStatus = new TSStatus(TSStatusCode.CREATE_REGION_ERROR.getStatusCode());
-        tsStatus.setMessage(consensusGenericResponse.getException().getMessage());
-      }
+      DataRegionConsensusImpl.getInstance().createLocalPeer(dataRegionId, peers);
+      tsStatus = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
     } catch (DataRegionException e) {
       LOGGER.error("Create Data Region {} failed because {}", storageGroup, e.getMessage());
       tsStatus = new TSStatus(TSStatusCode.CREATE_REGION_ERROR.getStatusCode());
       tsStatus.setMessage(String.format("Create Data Region failed because of %s", e.getMessage()));
+    } catch (ConsensusGroupAlreadyExistException e) {
+      tsStatus = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
+      tsStatus.setMessage(String.format("DataRegion %d already exists.", dataRegionId.getId()));
+    } catch (ConsensusException e) {
+      tsStatus = new TSStatus(TSStatusCode.CREATE_REGION_ERROR.getStatusCode());
+      tsStatus.setMessage(e.getMessage());
     }
     return tsStatus;
   }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/executor/RegionReadExecutor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/executor/RegionReadExecutor.java
index 4e2506a2d3f..9ac38701dac 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/executor/RegionReadExecutor.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/executor/RegionReadExecutor.java
@@ -23,7 +23,7 @@ import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import org.apache.iotdb.commons.consensus.DataRegionId;
 import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.consensus.IConsensus;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
+import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.db.consensus.DataRegionConsensusImpl;
 import org.apache.iotdb.db.consensus.SchemaRegionConsensusImpl;
 import org.apache.iotdb.db.queryengine.execution.fragment.FragmentInstanceInfo;
@@ -69,7 +69,7 @@ public class RegionReadExecutor {
   public RegionExecutionResult execute(
       ConsensusGroupId groupId, FragmentInstance fragmentInstance) {
     // execute fragment instance in state machine
-    ConsensusReadResponse readResponse;
+    DataSet readResponse;
     try (SetThreadName threadName = new SetThreadName(fragmentInstance.getId().getFullId())) {
       if (groupId instanceof DataRegionId) {
         readResponse = dataRegionConsensus.read(groupId, fragmentInstance);
@@ -81,20 +81,8 @@ public class RegionReadExecutor {
         LOGGER.error(RESPONSE_NULL_ERROR_MSG);
         resp.setAccepted(false);
         resp.setMessage(RESPONSE_NULL_ERROR_MSG);
-      } else if (!readResponse.isSuccess()) {
-        LOGGER.error(
-            "Execute FragmentInstance in ConsensusGroup {} failed.",
-            groupId,
-            readResponse.getException());
-        resp.setAccepted(false);
-        resp.setMessage(
-            String.format(
-                ERROR_MSG_FORMAT,
-                readResponse.getException() == null
-                    ? ""
-                    : readResponse.getException().getMessage()));
       } else {
-        FragmentInstanceInfo info = (FragmentInstanceInfo) readResponse.getDataset();
+        FragmentInstanceInfo info = (FragmentInstanceInfo) readResponse;
         resp.setAccepted(!info.getState().isFailed());
         resp.setMessage(info.getMessage());
       }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/executor/RegionWriteExecutor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/executor/RegionWriteExecutor.java
index c60787dd737..da0887365b6 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/executor/RegionWriteExecutor.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/executor/RegionWriteExecutor.java
@@ -31,7 +31,7 @@ import org.apache.iotdb.commons.service.metric.PerformanceOverviewMetrics;
 import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.consensus.IConsensus;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.consensus.DataRegionConsensusImpl;
@@ -164,28 +164,23 @@ public class RegionWriteExecutor {
         return response;
       }
 
-      ConsensusWriteResponse writeResponse =
-          executePlanNodeInConsensusLayer(context.getRegionId(), node);
-      if (writeResponse.getStatus() != null) {
-        response.setAccepted(
-            TSStatusCode.SUCCESS_STATUS.getStatusCode() == writeResponse.getStatus().getCode());
-        response.setMessage(writeResponse.getStatus().message);
-        response.setStatus(writeResponse.getStatus());
-      } else {
-        LOGGER.error(
-            "Something wrong happened while calling consensus layer's write API.",
-            writeResponse.getException());
+      try {
+        TSStatus status = executePlanNodeInConsensusLayer(context.getRegionId(), node);
+        response.setAccepted(TSStatusCode.SUCCESS_STATUS.getStatusCode() == status.getCode());
+        response.setMessage(status.getMessage());
+        response.setStatus(status);
+      } catch (ConsensusException e) {
+        LOGGER.error("Failed in the write API executing the consensus layer due to: ", e);
         response.setAccepted(false);
-        response.setMessage(writeResponse.getException().toString());
+        response.setMessage(e.toString());
         response.setStatus(
-            RpcUtils.getStatus(
-                TSStatusCode.EXECUTE_STATEMENT_ERROR, writeResponse.getErrorMessage()));
+            RpcUtils.getStatus(TSStatusCode.EXECUTE_STATEMENT_ERROR, e.getMessage()));
       }
       return response;
     }
 
-    private ConsensusWriteResponse executePlanNodeInConsensusLayer(
-        ConsensusGroupId groupId, PlanNode planNode) {
+    private TSStatus executePlanNodeInConsensusLayer(ConsensusGroupId groupId, PlanNode planNode)
+        throws ConsensusException {
       if (groupId instanceof DataRegionId) {
         return dataRegionConsensus.write(groupId, planNode);
       } else {
@@ -234,72 +229,57 @@ public class RegionWriteExecutor {
       RegionExecutionResult response = new RegionExecutionResult();
       context.getRegionWriteValidationRWLock().readLock().lock();
       try {
-
-        ConsensusWriteResponse writeResponse =
-            fireTriggerAndInsert(context.getRegionId(), insertNode);
-
-        if (writeResponse.getStatus() != null) {
-          response.setAccepted(
-              TSStatusCode.SUCCESS_STATUS.getStatusCode() == writeResponse.getStatus().getCode());
-          if (TSStatusCode.SUCCESS_STATUS.getStatusCode() != writeResponse.getStatus().getCode()) {
-            response.setMessage(writeResponse.getStatus().message);
-            response.setStatus(writeResponse.getStatus());
-          } else {
-            response.setMessage(writeResponse.getStatus().message);
-          }
-        } else {
-          LOGGER.warn(
-              "Something wrong happened while calling consensus layer's write API.",
-              writeResponse.getException());
-          response.setAccepted(false);
-          response.setMessage(writeResponse.getException().toString());
-          response.setStatus(
-              RpcUtils.getStatus(
-                  TSStatusCode.WRITE_PROCESS_ERROR, writeResponse.getException().toString()));
+        TSStatus status = fireTriggerAndInsert(context.getRegionId(), insertNode);
+        response.setAccepted(TSStatusCode.SUCCESS_STATUS.getStatusCode() == status.getCode());
+        response.setMessage(status.message);
+        if (!response.isAccepted()) {
+          response.setStatus(status);
         }
-
+        return response;
+      } catch (ConsensusException e) {
+        LOGGER.warn("Failed in the write API executing the consensus layer due to: ", e);
+        response.setAccepted(false);
+        response.setMessage(e.toString());
+        response.setStatus(RpcUtils.getStatus(TSStatusCode.WRITE_PROCESS_ERROR, e.toString()));
         return response;
       } finally {
         context.getRegionWriteValidationRWLock().readLock().unlock();
       }
     }
 
-    private ConsensusWriteResponse fireTriggerAndInsert(
-        ConsensusGroupId groupId, PlanNode planNode) {
+    private TSStatus fireTriggerAndInsert(ConsensusGroupId groupId, PlanNode planNode)
+        throws ConsensusException {
       long triggerCostTime = 0;
-      ConsensusWriteResponse writeResponse;
+      TSStatus status;
       long startTime = System.nanoTime();
       // fire Trigger before the insertion
       TriggerFireResult result = triggerFireVisitor.process(planNode, TriggerEvent.BEFORE_INSERT);
       triggerCostTime += (System.nanoTime() - startTime);
       if (result.equals(TriggerFireResult.TERMINATION)) {
-        TSStatus triggerError = new TSStatus(TSStatusCode.TRIGGER_FIRE_ERROR.getStatusCode());
-        triggerError.setMessage(
-            "Failed to complete the insertion because trigger error before the insertion.");
-        writeResponse = ConsensusWriteResponse.newBuilder().setStatus(triggerError).build();
+        status =
+            RpcUtils.getStatus(
+                TSStatusCode.TRIGGER_FIRE_ERROR.getStatusCode(),
+                "Failed to complete the insertion because trigger error before the insertion.");
       } else {
-        boolean hasFailedTriggerBeforeInsertion =
-            result.equals(TriggerFireResult.FAILED_NO_TERMINATION);
-
         long startWriteTime = System.nanoTime();
-        writeResponse = dataRegionConsensus.write(groupId, planNode);
+        status = dataRegionConsensus.write(groupId, planNode);
         PERFORMANCE_OVERVIEW_METRICS.recordScheduleStorageCost(System.nanoTime() - startWriteTime);
 
         // fire Trigger after the insertion
-        if (writeResponse.isSuccessful()) {
-          startTime = System.nanoTime();
-          result = triggerFireVisitor.process(planNode, TriggerEvent.AFTER_INSERT);
-          if (hasFailedTriggerBeforeInsertion || !result.equals(TriggerFireResult.SUCCESS)) {
-            TSStatus triggerError = new TSStatus(TSStatusCode.TRIGGER_FIRE_ERROR.getStatusCode());
-            triggerError.setMessage(
-                "Meet trigger error before/after the insertion, the insertion itself is completed.");
-            writeResponse = ConsensusWriteResponse.newBuilder().setStatus(triggerError).build();
-          }
-          triggerCostTime += (System.nanoTime() - startTime);
+        startTime = System.nanoTime();
+        boolean hasFailedTriggerBeforeInsertion =
+            result.equals(TriggerFireResult.FAILED_NO_TERMINATION);
+        result = triggerFireVisitor.process(planNode, TriggerEvent.AFTER_INSERT);
+        if (hasFailedTriggerBeforeInsertion || !result.equals(TriggerFireResult.SUCCESS)) {
+          status =
+              RpcUtils.getStatus(
+                  TSStatusCode.TRIGGER_FIRE_ERROR.getStatusCode(),
+                  "Meet trigger error before/after the insertion, the insertion itself is completed.");
         }
+        triggerCostTime += (System.nanoTime() - startTime);
       }
       PERFORMANCE_OVERVIEW_METRICS.recordScheduleTriggerCost(triggerCostTime);
-      return writeResponse;
+      return status;
     }
 
     @Override
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/template/ClusterTemplateManager.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/template/ClusterTemplateManager.java
index da89421d20a..42a907fa5f8 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/template/ClusterTemplateManager.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/template/ClusterTemplateManager.java
@@ -394,7 +394,7 @@ public class ClusterTemplateManager implements ITemplateManager {
   // This is used for template info sync when activating DataNode and registering into cluster. All
   // set and pre-set info will be updated.
   public void updateTemplateSetInfo(byte[] templateSetInfo) {
-    if (templateSetInfo == null) {
+    if (templateSetInfo == null || templateSetInfo.length == 0) {
       return;
     }
     readWriteLock.writeLock().lock();
@@ -405,6 +405,7 @@ public class ClusterTemplateManager implements ITemplateManager {
           TemplateInternalRPCUtil.parseAddAllTemplateSetInfoBytes(buffer);
       for (Map.Entry<Template, List<Pair<String, Boolean>>> entry :
           parsedTemplateSetInfo.entrySet()) {
+
         Template template = entry.getKey();
         templateIdMap.put(template.getId(), template);
         templateNameMap.put(template.getName(), template.getId());
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 37b4bb4a8d6..17af990eff5 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
@@ -481,8 +481,8 @@ public class DataNode implements DataNodeMBean {
     logger.info("IoTDB DataNode has started.");
 
     try {
-      SchemaRegionConsensusImpl.setupAndGetInstance().start();
-      DataRegionConsensusImpl.setupAndGetInstance().start();
+      SchemaRegionConsensusImpl.getInstance().start();
+      DataRegionConsensusImpl.getInstance().start();
     } catch (IOException e) {
       throw new StartupException(e);
     }
@@ -869,12 +869,8 @@ public class DataNode implements DataNodeMBean {
 
     try {
       MetricService.getInstance().stop();
-      if (SchemaRegionConsensusImpl.getInstance() != null) {
-        SchemaRegionConsensusImpl.getInstance().stop();
-      }
-      if (DataRegionConsensusImpl.getInstance() != null) {
-        DataRegionConsensusImpl.getInstance().stop();
-      }
+      SchemaRegionConsensusImpl.getInstance().stop();
+      DataRegionConsensusImpl.getInstance().stop();
     } catch (Exception e) {
       logger.error("Stop data node error", e);
     }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/IoTDBShutdownHook.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/IoTDBShutdownHook.java
index 4aac30f3e10..97d4efa204f 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/IoTDBShutdownHook.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/IoTDBShutdownHook.java
@@ -24,6 +24,7 @@ import org.apache.iotdb.commons.cluster.NodeStatus;
 import org.apache.iotdb.commons.concurrent.ThreadName;
 import org.apache.iotdb.commons.conf.CommonDescriptor;
 import org.apache.iotdb.consensus.ConsensusFactory;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.consensus.DataRegionConsensusImpl;
 import org.apache.iotdb.db.consensus.SchemaRegionConsensusImpl;
@@ -42,6 +43,8 @@ import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
+
 public class IoTDBShutdownHook extends Thread {
 
   private static final Logger logger = LoggerFactory.getLogger(IoTDBShutdownHook.class);
@@ -83,18 +86,24 @@ public class IoTDBShutdownHook extends Thread {
       DataRegionConsensusImpl.getInstance()
           .getAllConsensusGroupIds()
           .parallelStream()
-          .forEach(id -> DataRegionConsensusImpl.getInstance().triggerSnapshot(id));
+          .forEach(
+              id -> {
+                try {
+                  DataRegionConsensusImpl.getInstance().triggerSnapshot(id);
+                } catch (ConsensusException e) {
+                  logger.warn(
+                      "Something wrong happened while calling consensus layer's "
+                          + "triggerSnapshot API.",
+                      e);
+                }
+              });
     }
 
     // close consensusImpl
     try {
-      if (SchemaRegionConsensusImpl.getInstance() != null) {
-        SchemaRegionConsensusImpl.getInstance().stop();
-      }
-      if (DataRegionConsensusImpl.getInstance() != null) {
-        DataRegionConsensusImpl.getInstance().stop();
-      }
-    } catch (Exception e) {
+      SchemaRegionConsensusImpl.getInstance().stop();
+      DataRegionConsensusImpl.getInstance().stop();
+    } catch (IOException e) {
       logger.error("Stop ConsensusImpl error in IoTDBShutdownHook", e);
     }
 
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 35b495c8c1b..092394c9bf2 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
@@ -34,7 +34,9 @@ import org.apache.iotdb.commons.service.IService;
 import org.apache.iotdb.commons.service.ServiceType;
 import org.apache.iotdb.confignode.rpc.thrift.TRegionMigrateResultReportReq;
 import org.apache.iotdb.consensus.common.Peer;
-import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
+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.protocol.client.ConfigNodeClient;
@@ -215,19 +217,24 @@ public class RegionMigrateService implements IService {
           "{}, Start to addPeer {} for region {}", REGION_MIGRATE_PROCESS, destDataNode, tRegionId);
       ConsensusGroupId regionId = ConsensusGroupId.Factory.createFromTConsensusGroupId(tRegionId);
       TSStatus status = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
-      ConsensusGenericResponse resp = null;
       TEndPoint destEndpoint = getConsensusEndPoint(destDataNode, regionId);
       boolean addPeerSucceed = true;
+      Throwable throwable = null;
       for (int i = 0; i < MAX_RETRY_NUM; i++) {
         try {
           if (!addPeerSucceed) {
             Thread.sleep(SLEEP_MILLIS);
           }
-          resp =
-              addRegionPeer(
-                  regionId, new Peer(regionId, destDataNode.getDataNodeId(), destEndpoint));
-        } catch (Throwable e) {
+          addRegionPeer(regionId, new Peer(regionId, destDataNode.getDataNodeId(), destEndpoint));
+          addPeerSucceed = true;
+        } catch (PeerAlreadyInConsensusGroupException e) {
+          addPeerSucceed = true;
+        } catch (InterruptedException e) {
+          throwable = e;
+          Thread.currentThread().interrupt();
+        } catch (ConsensusException e) {
           addPeerSucceed = false;
+          throwable = e;
           taskLogger.error(
               "{}, executed addPeer {} for region {} error, retry times: {}",
               REGION_MIGRATE_PROCESS,
@@ -236,17 +243,17 @@ public class RegionMigrateService implements IService {
               i,
               e);
         }
-        if (addPeerSucceed && resp != null && resp.isSuccess()) {
+        if (addPeerSucceed || throwable instanceof InterruptedException) {
           break;
         }
       }
 
-      if (!addPeerSucceed || resp == null || !resp.isSuccess()) {
+      if (!addPeerSucceed) {
         String errorMsg =
             String.format(
-                "%s, AddPeer for region error after max retry times, peerId: %s, regionId: %s, resp: %s",
-                REGION_MIGRATE_PROCESS, destEndpoint, regionId, resp);
-        taskLogger.error(errorMsg);
+                "%s, AddPeer for region error after max retry times, peerId: %s, regionId: %s",
+                REGION_MIGRATE_PROCESS, destEndpoint, regionId);
+        taskLogger.error(errorMsg, throwable);
         status.setCode(TSStatusCode.MIGRATE_REGION_ERROR.getStatusCode());
         status.setMessage(errorMsg);
         return status;
@@ -262,14 +269,12 @@ public class RegionMigrateService implements IService {
       return status;
     }
 
-    private ConsensusGenericResponse addRegionPeer(ConsensusGroupId regionId, Peer newPeer) {
-      ConsensusGenericResponse resp;
+    private void addRegionPeer(ConsensusGroupId regionId, Peer newPeer) throws ConsensusException {
       if (regionId instanceof DataRegionId) {
-        resp = DataRegionConsensusImpl.getInstance().addPeer(regionId, newPeer);
+        DataRegionConsensusImpl.getInstance().addRemotePeer(regionId, newPeer);
       } else {
-        resp = SchemaRegionConsensusImpl.getInstance().addPeer(regionId, newPeer);
+        SchemaRegionConsensusImpl.getInstance().addRemotePeer(regionId, newPeer);
       }
-      return resp;
     }
   }
 
@@ -305,18 +310,24 @@ public class RegionMigrateService implements IService {
           REGION_MIGRATE_PROCESS,
           destEndPoint,
           regionId);
-      ConsensusGenericResponse resp = null;
+      Throwable throwable = null;
       boolean removePeerSucceed = true;
       for (int i = 0; i < MAX_RETRY_NUM; i++) {
         try {
           if (!removePeerSucceed) {
             Thread.sleep(SLEEP_MILLIS);
           }
-          resp =
-              removeRegionPeer(
-                  regionId, new Peer(regionId, destDataNode.getDataNodeId(), destEndPoint));
-        } catch (Throwable e) {
+          removeRegionPeer(
+              regionId, new Peer(regionId, destDataNode.getDataNodeId(), destEndPoint));
+          removePeerSucceed = true;
+        } catch (PeerNotInConsensusGroupException e) {
+          removePeerSucceed = true;
+        } catch (InterruptedException e) {
+          throwable = e;
+          Thread.currentThread().interrupt();
+        } catch (ConsensusException e) {
           removePeerSucceed = false;
+          throwable = e;
           taskLogger.error(
               "{}, executed removePeer {} for region {} error, retry times: {}",
               REGION_MIGRATE_PROCESS,
@@ -325,17 +336,17 @@ public class RegionMigrateService implements IService {
               i,
               e);
         }
-        if (removePeerSucceed && resp != null && resp.isSuccess()) {
+        if (removePeerSucceed || throwable instanceof InterruptedException) {
           break;
         }
       }
 
-      if (!removePeerSucceed || resp == null || !resp.isSuccess()) {
+      if (!removePeerSucceed) {
         String errorMsg =
             String.format(
-                "%s, RemovePeer for region error after max retry times, peerId: %s, regionId: %s, resp: %s",
-                REGION_MIGRATE_PROCESS, destEndPoint, regionId, resp);
-        taskLogger.error(errorMsg);
+                "%s, RemovePeer for region error after max retry times, peerId: %s, regionId: %s",
+                REGION_MIGRATE_PROCESS, destEndPoint, regionId);
+        taskLogger.error(errorMsg, throwable);
         status.setCode(TSStatusCode.MIGRATE_REGION_ERROR.getStatusCode());
         status.setMessage(errorMsg);
         return status;
@@ -351,14 +362,13 @@ public class RegionMigrateService implements IService {
       return status;
     }
 
-    private ConsensusGenericResponse removeRegionPeer(ConsensusGroupId regionId, Peer oldPeer) {
-      ConsensusGenericResponse resp;
+    private void removeRegionPeer(ConsensusGroupId regionId, Peer oldPeer)
+        throws ConsensusException {
       if (regionId instanceof DataRegionId) {
-        resp = DataRegionConsensusImpl.getInstance().removePeer(regionId, oldPeer);
+        DataRegionConsensusImpl.getInstance().removeRemotePeer(regionId, oldPeer);
       } else {
-        resp = SchemaRegionConsensusImpl.getInstance().removePeer(regionId, oldPeer);
+        SchemaRegionConsensusImpl.getInstance().removeRemotePeer(regionId, oldPeer);
       }
-      return resp;
     }
   }
 
@@ -406,29 +416,26 @@ public class RegionMigrateService implements IService {
           tRegionId);
       ConsensusGroupId regionId = ConsensusGroupId.Factory.createFromTConsensusGroupId(tRegionId);
       TSStatus status = new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
-      ConsensusGenericResponse resp;
       try {
         if (regionId instanceof DataRegionId) {
-          resp = DataRegionConsensusImpl.getInstance().deletePeer(regionId);
+          DataRegionConsensusImpl.getInstance().deleteLocalPeer(regionId);
         } else {
-          resp = SchemaRegionConsensusImpl.getInstance().deletePeer(regionId);
+          SchemaRegionConsensusImpl.getInstance().deleteLocalPeer(regionId);
         }
-      } catch (Throwable e) {
-        taskLogger.error("{}, deletePeer error, regionId: {}", REGION_MIGRATE_PROCESS, regionId, e);
-        status.setCode(TSStatusCode.MIGRATE_REGION_ERROR.getStatusCode());
-        status.setMessage(
-            "deletePeer for region: " + regionId + " error. exception: " + e.getMessage());
-        return status;
-      }
-      if (!resp.isSuccess()) {
+      } catch (ConsensusException e) {
         String errorMsg =
             String.format(
-                "deletePeer error, regionId: %s, errorMessage: %s",
-                regionId, resp.getException().getMessage());
+                "deletePeer error, regionId: %s, errorMessage: %s", regionId, e.getMessage());
         taskLogger.error(errorMsg);
         status.setCode(TSStatusCode.MIGRATE_REGION_ERROR.getStatusCode());
         status.setMessage(errorMsg);
         return status;
+      } catch (Exception e) {
+        taskLogger.error("{}, deletePeer error, regionId: {}", REGION_MIGRATE_PROCESS, regionId, e);
+        status.setCode(TSStatusCode.MIGRATE_REGION_ERROR.getStatusCode());
+        status.setMessage(
+            "deletePeer for region: " + regionId + " error. exception: " + e.getMessage());
+        return status;
       }
       taskLogger.info(
           "{}, Succeed to deletePeer {} from consensus group", REGION_MIGRATE_PROCESS, regionId);
@@ -450,7 +457,7 @@ public class RegionMigrateService implements IService {
         } else {
           SchemaEngine.getInstance().deleteSchemaRegion((SchemaRegionId) regionId);
         }
-      } catch (Throwable e) {
+      } catch (Exception e) {
         taskLogger.error("{}, deleteRegion {} error", REGION_MIGRATE_PROCESS, regionId, e);
         status.setCode(TSStatusCode.DELETE_REGION_ERROR.getStatusCode());
         status.setMessage("deleteRegion " + regionId + " error, " + e.getMessage());
@@ -476,7 +483,7 @@ public class RegionMigrateService implements IService {
     TRegionMigrateResultReportReq req = new TRegionMigrateResultReportReq(tRegionId, status);
     try {
       reportRegionMigrateResultToConfigNode(req);
-    } catch (Throwable e) {
+    } catch (Exception e) {
       LOGGER.error(
           "{}, Report region {} migrate result error in reportSucceed, result: {}",
           REGION_MIGRATE_PROCESS,
@@ -497,7 +504,7 @@ public class RegionMigrateService implements IService {
     req.setFailedNodeAndReason(failedNodeAndReason);
     try {
       reportRegionMigrateResultToConfigNode(req);
-    } catch (Throwable e) {
+    } catch (Exception e) {
       LOGGER.error(
           "{}, Report region {} migrate error in reportFailed, result:{}",
           REGION_MIGRATE_PROCESS,
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/executor/RegionReadExecutorTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/executor/RegionReadExecutorTest.java
index 9ae205aebef..016fe90b460 100644
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/executor/RegionReadExecutorTest.java
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/executor/RegionReadExecutorTest.java
@@ -23,7 +23,6 @@ import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import org.apache.iotdb.commons.consensus.DataRegionId;
 import org.apache.iotdb.commons.consensus.SchemaRegionId;
 import org.apache.iotdb.consensus.IConsensus;
-import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
 import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.queryengine.common.FragmentInstanceId;
 import org.apache.iotdb.db.queryengine.common.PlanFragmentId;
@@ -46,7 +45,7 @@ import static org.junit.Assert.assertTrue;
 public class RegionReadExecutorTest {
 
   @Test
-  public void testSuccessfulExecute() {
+  public void testSuccessfulExecute() throws ConsensusException {
 
     // data query
     ConsensusGroupId dataRegionGroupId = new DataRegionId(1);
@@ -62,15 +61,12 @@ public class RegionReadExecutorTest {
     RegionReadExecutor executor =
         new RegionReadExecutor(dataRegionConsensus, schemaRegionConsensus, fragmentInstanceManager);
 
-    ConsensusReadResponse readResponse = Mockito.mock(ConsensusReadResponse.class);
-    Mockito.when(readResponse.isSuccess()).thenReturn(true);
     FragmentInstanceInfo fragmentInstanceInfo = Mockito.mock(FragmentInstanceInfo.class);
-    Mockito.when(readResponse.getDataset()).thenReturn(fragmentInstanceInfo);
     Mockito.when(fragmentInstanceInfo.getState()).thenReturn(RUNNING);
     Mockito.when(fragmentInstanceInfo.getMessage()).thenReturn("data-success");
 
     Mockito.when(dataRegionConsensus.read(dataRegionGroupId, fragmentInstance))
-        .thenReturn(readResponse);
+        .thenReturn(fragmentInstanceInfo);
 
     RegionExecutionResult res = executor.execute(dataRegionGroupId, fragmentInstance);
 
@@ -80,13 +76,11 @@ public class RegionReadExecutorTest {
     // schema query
     ConsensusGroupId schemaRegionGroupId = new SchemaRegionId(1);
 
-    Mockito.when(readResponse.isSuccess()).thenReturn(true);
-    Mockito.when(readResponse.getDataset()).thenReturn(fragmentInstanceInfo);
     Mockito.when(fragmentInstanceInfo.getState()).thenReturn(RUNNING);
     Mockito.when(fragmentInstanceInfo.getMessage()).thenReturn("schema-success");
 
     Mockito.when(schemaRegionConsensus.read(schemaRegionGroupId, fragmentInstance))
-        .thenReturn(readResponse);
+        .thenReturn(fragmentInstanceInfo);
 
     res = executor.execute(schemaRegionGroupId, fragmentInstance);
 
@@ -95,7 +89,7 @@ public class RegionReadExecutorTest {
   }
 
   @Test
-  public void testResponseNullExecute() {
+  public void testResponseNullExecute() throws ConsensusException {
 
     // data query
     ConsensusGroupId dataRegionGroupId = new DataRegionId(1);
@@ -131,7 +125,7 @@ public class RegionReadExecutorTest {
   }
 
   @Test
-  public void testFailedExecute() {
+  public void testFailedExecute() throws ConsensusException {
 
     // data query
     ConsensusGroupId dataRegionGroupId = new DataRegionId(1);
@@ -147,12 +141,8 @@ public class RegionReadExecutorTest {
     RegionReadExecutor executor =
         new RegionReadExecutor(dataRegionConsensus, schemaRegionConsensus, fragmentInstanceManager);
 
-    ConsensusReadResponse readResponse = Mockito.mock(ConsensusReadResponse.class);
-    Mockito.when(readResponse.isSuccess()).thenReturn(false);
-    Mockito.when(readResponse.getException()).thenReturn(new ConsensusException("data-exception"));
-
     Mockito.when(dataRegionConsensus.read(dataRegionGroupId, fragmentInstance))
-        .thenReturn(readResponse);
+        .thenThrow(new ConsensusException("data-exception"));
 
     RegionExecutionResult res = executor.execute(dataRegionGroupId, fragmentInstance);
 
@@ -162,20 +152,17 @@ public class RegionReadExecutorTest {
     // schema query
     ConsensusGroupId schemaRegionGroupId = new SchemaRegionId(1);
 
-    Mockito.when(readResponse.isSuccess()).thenReturn(false);
-    Mockito.when(readResponse.getException()).thenReturn(null);
-
     Mockito.when(schemaRegionConsensus.read(schemaRegionGroupId, fragmentInstance))
-        .thenReturn(readResponse);
+        .thenThrow(new ConsensusException("schema-exception"));
 
     res = executor.execute(schemaRegionGroupId, fragmentInstance);
 
     assertFalse(res.isAccepted());
-    assertEquals(String.format(ERROR_MSG_FORMAT, ""), res.getMessage());
+    assertEquals(String.format(ERROR_MSG_FORMAT, "schema-exception"), res.getMessage());
   }
 
   @Test
-  public void testExceptionHappened() {
+  public void testExceptionHappened() throws ConsensusException {
 
     ConsensusGroupId dataRegionGroupId = new DataRegionId(1);
     FragmentInstanceId fragmentInstanceId =
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/executor/RegionWriteExecutorTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/executor/RegionWriteExecutorTest.java
index 6e8eafd851c..f1f6dfe0132 100644
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/executor/RegionWriteExecutorTest.java
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/executor/RegionWriteExecutorTest.java
@@ -25,7 +25,7 @@ import org.apache.iotdb.commons.consensus.DataRegionId;
 import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.consensus.IConsensus;
-import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.db.protocol.thrift.impl.DataNodeRegionManager;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertRowNode;
@@ -49,7 +49,7 @@ import static org.junit.Assert.fail;
 public class RegionWriteExecutorTest {
 
   @Test
-  public void testInsertRowNode() {
+  public void testInsertRowNode() throws ConsensusException {
 
     IConsensus dataRegionConsensus = Mockito.mock(IConsensus.class);
     IConsensus schemaRegionConsensus = Mockito.mock(IConsensus.class);
@@ -79,22 +79,17 @@ public class RegionWriteExecutorTest {
     Mockito.when(regionManager.getRegionLock(dataRegionGroupId))
         .thenReturn(new ReentrantReadWriteLock());
 
-    ConsensusWriteResponse writeResponse = Mockito.mock(ConsensusWriteResponse.class);
-    Mockito.when(dataRegionConsensus.write(dataRegionGroupId, planNode)).thenReturn(writeResponse);
-
-    Mockito.when(writeResponse.getStatus()).thenReturn(null);
-
-    RegionExecutionResult res = executor.execute(dataRegionGroupId, planNode);
-    assertFalse(res.isAccepted());
+    TSStatus writeResponse = Mockito.mock(TSStatus.class);
+    Mockito.when(writeResponse.getCode()).thenReturn(TSStatusCode.SUCCESS_STATUS.getStatusCode());
 
     Mockito.when(triggerFireVisitor.process(planNode, TriggerEvent.BEFORE_INSERT))
         .thenReturn(TriggerFireResult.TERMINATION);
-    res = executor.execute(dataRegionGroupId, planNode);
+    RegionExecutionResult res = executor.execute(dataRegionGroupId, planNode);
     assertFalse(res.isAccepted());
 
     Mockito.when(triggerFireVisitor.process(planNode, TriggerEvent.BEFORE_INSERT))
         .thenReturn(TriggerFireResult.SUCCESS);
-    Mockito.when(writeResponse.isSuccessful()).thenReturn(true);
+    Mockito.when(dataRegionConsensus.write(dataRegionGroupId, planNode)).thenReturn(writeResponse);
     Mockito.when(triggerFireVisitor.process(planNode, TriggerEvent.AFTER_INSERT))
         .thenReturn(TriggerFireResult.TERMINATION);
     res = executor.execute(dataRegionGroupId, planNode);
@@ -102,10 +97,13 @@ public class RegionWriteExecutorTest {
 
     Mockito.when(triggerFireVisitor.process(planNode, TriggerEvent.AFTER_INSERT))
         .thenReturn(TriggerFireResult.SUCCESS);
-    Mockito.when(writeResponse.getStatus())
-        .thenReturn(new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode()));
     res = executor.execute(dataRegionGroupId, planNode);
     assertTrue(res.isAccepted());
+
+    Mockito.when(dataRegionConsensus.write(dataRegionGroupId, planNode))
+        .thenThrow(new ConsensusException("Error!"));
+    res = executor.execute(dataRegionGroupId, planNode);
+    assertFalse(res.isAccepted());
   }
 
   private InsertRowNode getInsertRowNode() throws IllegalPathException {
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/service/DataNodeInternalRPCServiceImplTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/service/DataNodeInternalRPCServiceImplTest.java
index 8d5a9fff2c8..c72267e256e 100644
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/service/DataNodeInternalRPCServiceImplTest.java
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/service/DataNodeInternalRPCServiceImplTest.java
@@ -81,8 +81,8 @@ public class DataNodeInternalRPCServiceImplTest {
     SchemaEngine.getInstance().init();
     SchemaEngine.getInstance()
         .createSchemaRegion(new PartialPath("root.ln"), new SchemaRegionId(0));
-    DataRegionConsensusImpl.setupAndGetInstance().start();
-    SchemaRegionConsensusImpl.setupAndGetInstance().start();
+    DataRegionConsensusImpl.getInstance().start();
+    SchemaRegionConsensusImpl.getInstance().start();
     DataNodeRegionManager.getInstance().init();
   }
 
@@ -90,7 +90,7 @@ public class DataNodeInternalRPCServiceImplTest {
   public void setUp() throws Exception {
     TRegionReplicaSet regionReplicaSet = genRegionReplicaSet();
     SchemaRegionConsensusImpl.getInstance()
-        .createPeer(
+        .createLocalPeer(
             ConsensusGroupId.Factory.createFromTConsensusGroupId(regionReplicaSet.getRegionId()),
             genSchemaRegionPeerList(regionReplicaSet));
     dataNodeInternalRPCServiceImpl = new DataNodeInternalRPCServiceImpl();
@@ -100,7 +100,7 @@ public class DataNodeInternalRPCServiceImplTest {
   public void tearDown() throws Exception {
     TRegionReplicaSet regionReplicaSet = genRegionReplicaSet();
     SchemaRegionConsensusImpl.getInstance()
-        .deletePeer(
+        .deleteLocalPeer(
             ConsensusGroupId.Factory.createFromTConsensusGroupId(regionReplicaSet.getRegionId()));
     FileUtils.deleteFully(new File(conf.getConsensusDir()));
   }
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/consensus/ConsensusGroupId.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/consensus/ConsensusGroupId.java
index f3030d6af6a..589ff19e6fa 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/consensus/ConsensusGroupId.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/consensus/ConsensusGroupId.java
@@ -24,17 +24,25 @@ import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
 
 import java.util.Objects;
 
-// we abstract this class to hide word `ConsensusGroup` for IoTDB StorageEngine/SchemaEngine
+/** we abstract this class to hide word `ConsensusGroup` for IoTDB StorageEngine/SchemaEngine. */
 public abstract class ConsensusGroupId {
 
   protected int id;
 
-  // return specific id
+  /**
+   * get specific id.
+   *
+   * @return id.
+   */
   public int getId() {
     return id;
   }
 
-  // return specific type
+  /**
+   * get specific type.
+   *
+   * @return type.
+   */
   public abstract TConsensusGroupType getType();
 
   public TConsensusGroupId convertToTConsensusGroupId() {
@@ -65,6 +73,10 @@ public abstract class ConsensusGroupId {
 
   public static class Factory {
 
+    private Factory() {
+      // empty constructor
+    }
+
     public static ConsensusGroupId create(int type, int id) {
       ConsensusGroupId groupId;
       if (type == TConsensusGroupType.DataRegion.getValue()) {
@@ -85,24 +97,4 @@ public abstract class ConsensusGroupId {
       return create(tConsensusGroupId.getType().getValue(), tConsensusGroupId.getId());
     }
   }
-
-  public static String formatTConsensusGroupId(TConsensusGroupId groupId) {
-    StringBuilder format = new StringBuilder();
-
-    switch (groupId.getType()) {
-      case SchemaRegion:
-        format.append("SchemaRegion");
-        break;
-      case DataRegion:
-        format.append("DataRegion");
-        break;
-      case ConfigRegion:
-        format.append("ConfigRegion");
-        break;
-    }
-
-    format.append("(").append(groupId.getId()).append(")");
-
-    return format.toString();
-  }
 }
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/StatusUtils.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/StatusUtils.java
index 6cb401b56fa..83f041b0f6e 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/StatusUtils.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/StatusUtils.java
@@ -139,7 +139,7 @@ public class StatusUtils {
         status.setMessage("Meet error in close operation.");
         break;
       case SYSTEM_READ_ONLY:
-        status.setMessage("Database is read-only.");
+        status.setMessage("Fail to do non-query operations because system is read-only.");
         break;
       case DISK_SPACE_INSUFFICIENT:
         status.setMessage("Disk space is insufficient.");
diff --git a/iotdb-protocol/thrift-iot-consensus/pom.xml b/iotdb-protocol/thrift-consensus/pom.xml
similarity index 94%
rename from iotdb-protocol/thrift-iot-consensus/pom.xml
rename to iotdb-protocol/thrift-consensus/pom.xml
index ba8d846c4a2..80d664b8e3f 100644
--- a/iotdb-protocol/thrift-iot-consensus/pom.xml
+++ b/iotdb-protocol/thrift-consensus/pom.xml
@@ -27,9 +27,9 @@
         <version>1.2.0-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
-    <artifactId>thrift-iot-consensus</artifactId>
-    <name>rpc-thrift-iot-consensus</name>
-    <description>Rpc modules for iot consensus algorithm</description>
+    <artifactId>iotdb-thrift-consensus</artifactId>
+    <name>IoTDB: Protocol: Thrift Consensus</name>
+    <description>RPC modules for consensus</description>
     <dependencies>
         <dependency>
             <groupId>org.apache.thrift</groupId>
diff --git a/iotdb-protocol/thrift-iot-consensus/src/main/thrift/iotconsensus.thrift b/iotdb-protocol/thrift-consensus/src/main/thrift/iotconsensus.thrift
similarity index 100%
rename from iotdb-protocol/thrift-iot-consensus/src/main/thrift/iotconsensus.thrift
rename to iotdb-protocol/thrift-consensus/src/main/thrift/iotconsensus.thrift
diff --git a/pom.xml b/pom.xml
index f7a49ea2e98..654b774babb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,7 +84,7 @@
         <module>iotdb-protocol/thrift</module>
         <module>iotdb-protocol/thrift-commons</module>
         <module>iotdb-protocol/thrift-confignode</module>
-        <module>iotdb-protocol/thrift-iot-consensus</module>
+        <module>iotdb-protocol/thrift-consensus</module>
         <module>iotdb-protocol/thrift-mlnode</module>
         <module>iotdb-client/service-rpc</module>
         <module>iotdb-client/jdbc</module>
@@ -819,7 +819,7 @@
                         <sourceDirectory>iotdb-protocol/thrift/target/generated-sources/thrift</sourceDirectory>
                         <sourceDirectory>iotdb-protocol/thrift-commons/target/generated-sources/thrift</sourceDirectory>
                         <sourceDirectory>iotdb-protocol/thrift-confignode/target/generated-sources/thrift</sourceDirectory>
-                        <sourceDirectory>iotdb-protocol/thrift-iot-consensus/target/generated-sources/thrift</sourceDirectory>
+                        <sourceDirectory>iotdb-protocol/thrift-consensus/target/generated-sources/thrift</sourceDirectory>
                         <sourceDirectory>iotdb-protocol/openapi/target/generated-sources/java/src/gen/java</sourceDirectory>
                         <sourceDirectory>iotdb-protocol/openapi/target/generated-sources/java/src/main/java</sourceDirectory>
                         <sourceDirectory>iotdb-core/datanode/target/generated-sources/freemarker/</sourceDirectory>