From f228cfdd00364bcefb7d00928886d5bbf51a1bb8 Mon Sep 17 00:00:00 2001
From: WenYao <729673078@qq.com>
Date: Mon, 27 Feb 2023 10:20:23 +0800
Subject: [PATCH] [enhancement](session-variable)add a use_fix_replica session
variable to fix query replica (#17101)
Add use_fix_replica session variable, so that we can be better debug replica inconsistencies problem.
If use_fix_replica default is -1, which means not fix,
else we will choose the {use_fix_replica} smallest replica.
---
docs/en/docs/advanced/variables.md | 4 ++++
docs/zh-CN/docs/advanced/variables.md | 4 ++++
.../java/org/apache/doris/catalog/Replica.java | 17 +++++++++++++++++
.../org/apache/doris/planner/OlapScanNode.java | 15 ++++++++++++++-
.../org/apache/doris/qe/SessionVariable.java | 7 +++++++
5 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/docs/en/docs/advanced/variables.md b/docs/en/docs/advanced/variables.md
index 2d82126091..c4d2e6f983 100644
--- a/docs/en/docs/advanced/variables.md
+++ b/docs/en/docs/advanced/variables.md
@@ -590,3 +590,7 @@ Translated with www.DeepL.com/Translator (free version)
Controls whether to show each user's implicit roles in the results of `show roles`. Default is false.
+
+* `use_fix_replica`
+
+ Use a fixed replica to query. If use_fix_replica is 1, the smallest one is used, if use_fix_replica is 2, the second smallest one is used, and so on. The default value is -1, which means it is not enabled.
diff --git a/docs/zh-CN/docs/advanced/variables.md b/docs/zh-CN/docs/advanced/variables.md
index f67f02ef90..98af616bab 100644
--- a/docs/zh-CN/docs/advanced/variables.md
+++ b/docs/zh-CN/docs/advanced/variables.md
@@ -577,3 +577,7 @@ SELECT /*+ SET_VAR(query_timeout = 1, enable_partition_cache=true) */ sleep(3);
控制是否在 `show roles` 的结果里显示每个用户隐式对应的角色。默认为 false。
+
+* `use_fix_replica`
+
+ 使用固定的replica进行查询,该值表示固定使用第几小的replica,默认为-1表示不启用。
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Replica.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Replica.java
index ce891a521d..fb8b834787 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Replica.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Replica.java
@@ -36,6 +36,7 @@ import java.util.Comparator;
public class Replica implements Writable {
private static final Logger LOG = LogManager.getLogger(Replica.class);
public static final VersionComparator VERSION_DESC_COMPARATOR = new VersionComparator();
+ public static final IdComparator ID_COMPARATOR = new IdComparator();
public enum ReplicaState {
NORMAL,
@@ -538,6 +539,22 @@ public class Replica implements Writable {
}
}
+ private static class IdComparator implements Comparator {
+ public IdComparator() {
+ }
+
+ @Override
+ public int compare(T replica1, T replica2) {
+ if (replica1.getId() < replica2.getId()) {
+ return -1;
+ } else if (replica1.getId() == replica2.getId()) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ }
+
public void setWatermarkTxnId(long watermarkTxnId) {
this.watermarkTxnId = watermarkTxnId;
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java
index 1baa1a8cf6..09a2e2a966 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java
@@ -684,7 +684,20 @@ public class OlapScanNode extends ScanNode {
throw new UserException("Failed to get scan range, no queryable replica found in tablet: " + tabletId);
}
- Collections.shuffle(replicas);
+ int useFixReplica = -1;
+ if (ConnectContext.get() != null) {
+ useFixReplica = ConnectContext.get().getSessionVariable().useFixReplica;
+ }
+ if (useFixReplica == -1) {
+ Collections.shuffle(replicas);
+ } else {
+ LOG.debug("use fix replica, value: {}, replica num: {}", useFixReplica, replicas.size());
+ // sort by replica id
+ replicas.sort(Replica.ID_COMPARATOR);
+ Replica replica = replicas.get(useFixReplica >= replicas.size() ? replicas.size() - 1 : useFixReplica);
+ replicas.clear();
+ replicas.add(replica);
+ }
boolean tabletIsNull = true;
boolean collectedStat = false;
List errs = Lists.newArrayList();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index a3d844a160..54eec46afa 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -275,6 +275,9 @@ public class SessionVariable implements Serializable, Writable {
public static final String SHOW_USER_DEFAULT_ROLE = "show_user_default_role";
+ // fix replica to query. If num = 1, query the smallest replica, if 2 is the second smallest replica.
+ public static final String USE_FIX_REPLICA = "use_fix_replica";
+
// session origin value
public Map sessionOriginValue = new HashMap();
// check stmt is or not [select /*+ SET_VAR(...)*/ ...]
@@ -730,6 +733,10 @@ public class SessionVariable implements Serializable, Writable {
@VariableMgr.VarAttr(name = SHOW_USER_DEFAULT_ROLE, needForward = true)
public boolean showUserDefaultRole = false;
+ // Default value is -1, which means not fix replica
+ @VariableMgr.VarAttr(name = USE_FIX_REPLICA)
+ public int useFixReplica = -1;
+
// If this fe is in fuzzy mode, then will use initFuzzyModeVariables to generate some variables,
// not the default value set in the code.
public void initFuzzyModeVariables() {