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

yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new a2815f50805 branch-4.1: [improvement](fe) Reduce cloud version sync 
config (#66296) (#67929)
a2815f50805 is described below

commit a2815f50805a638d0c435a6e20cec83ab0ca59a4
Author: meiyi <[email protected]>
AuthorDate: Tue Sep 15 12:01:01 2026 +0800

    branch-4.1: [improvement](fe) Reduce cloud version sync config (#66296) 
(#67929)
    
    pick https://github.com/apache/doris/pull/66296
---
 .../main/java/org/apache/doris/common/Config.java  |  7 ++-
 .../java/org/apache/doris/catalog/OlapTable.java   |  6 +-
 .../apache/doris/cloud/catalog/CloudPartition.java | 18 ++++--
 .../cloud/catalog/CloudSyncVersionDaemon.java      | 14 ++++-
 .../org/apache/doris/cloud/rpc/VersionHelper.java  | 26 +++++---
 .../org/apache/doris/catalog/OlapTableTest.java    |  2 +-
 .../doris/cloud/catalog/CloudPartitionTest.java    | 28 ++++++++-
 .../apache/doris/cloud/rpc/VersionHelperTest.java  | 70 ++++++++++++++++++++++
 8 files changed, 152 insertions(+), 19 deletions(-)

diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java 
b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
index 55a531c054b..031d2584590 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
@@ -3890,7 +3890,7 @@ public class Config extends ConfigBase {
 
     @ConfField(description = {"存算分离模式下同步 table 和 partition version 的间隔. 所有 
frontend 都会检查",
             "Cloud table and partition version syncer interval. All frontends 
will perform the checking"})
-    public static int cloud_version_syncer_interval_second = 20;
+    public static int cloud_version_syncer_interval_second = 60;
 
     @ConfField(mutable = true, description = {"存算分离模式下是否启用同步 table 和 partition 
version 的功能",
             "Whether to enable the function of syncing table and partition 
version in cloud mode"})
@@ -3905,7 +3905,10 @@ public class Config extends ConfigBase {
 
     @ConfField(mutable = true, description = {"Get version task 包含的 table 或 
partition 数目的 batch size",
             "Maximal table or partition batch size of get version task."})
-    public static int cloud_get_version_task_batch_size = 2000;
+    public static int cloud_get_version_task_batch_size = 200;
+
+    @ConfField(mutable = true, description = {"Maximum retry times for cloud 
version syncer get version tasks."})
+    public static int cloud_version_syncer_get_version_retry_times = 3;
 
     @ConfField(mutable = true, description = {"schema change job 失败是否重试",
             "Whether to enable retry when a schema change job fails, default 
is true."})
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
index 5aa46f8a57b..af7b21e2594 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
@@ -3545,6 +3545,10 @@ public class OlapTable extends Table implements 
MTMVRelatedTableIf, GsonPostProc
     }
 
     public static List<Long> getVisibleVersionFromMeta(List<Long> dbIds, 
List<Long> tableIds) {
+        return getVisibleVersionFromMeta(dbIds, tableIds, 
Config.metaServiceRpcRetryTimes());
+    }
+
+    public static List<Long> getVisibleVersionFromMeta(List<Long> dbIds, 
List<Long> tableIds, int maxAttempts) {
         // get version rpc
         Cloud.GetVersionRequest request = Cloud.GetVersionRequest.newBuilder()
                 .setRequestIp(FrontendOptions.getLocalHostAddressCached())
@@ -3558,7 +3562,7 @@ public class OlapTable extends Table implements 
MTMVRelatedTableIf, GsonPostProc
                 .build();
 
         try {
-            Cloud.GetVersionResponse resp = 
VersionHelper.getVersionFromMeta(request);
+            Cloud.GetVersionResponse resp = 
VersionHelper.getVersionFromMeta(request, maxAttempts);
             if (resp.getStatus().getCode() != Cloud.MetaServiceCode.OK) {
                 throw new RpcException("get table visible version", 
"unexpected status " + resp.getStatus());
             }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudPartition.java 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudPartition.java
index d518721fabe..cfb9fabe907 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudPartition.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudPartition.java
@@ -228,6 +228,12 @@ public class CloudPartition extends Partition {
     // Return the visible version in order of the specified partition ids
     public static List<Long> getSnapshotVisibleVersionFromMs(
             List<CloudPartition> partitions, boolean waitForPendingTxns) 
throws RpcException {
+        return getSnapshotVisibleVersionFromMs(
+                partitions, waitForPendingTxns, 
Config.metaServiceRpcRetryTimes());
+    }
+
+    public static List<Long> getSnapshotVisibleVersionFromMs(
+            List<CloudPartition> partitions, boolean waitForPendingTxns, int 
maxAttempts) throws RpcException {
         if (partitions.isEmpty()) {
             return new ArrayList<>();
         }
@@ -243,7 +249,7 @@ public class CloudPartition extends Partition {
         }
 
         List<Long> versions = getSnapshotVisibleVersion(
-                dbIds, tableIds, partitionIds, versionUpdateTimesMs, 
waitForPendingTxns);
+                dbIds, tableIds, partitionIds, versionUpdateTimesMs, 
waitForPendingTxns, maxAttempts);
 
         // Cache visible version, see hasData() for details.
         int size = versions.size();
@@ -290,8 +296,10 @@ public class CloudPartition extends Partition {
             return Collections.emptyList();
         }
 
-        long cloudPartitionVersionCacheTtlMs = ConnectContext.get() == null ? 0
-                : 
ConnectContext.get().getSessionVariable().cloudPartitionVersionCacheTtlMs;
+        ConnectContext ctx = ConnectContext.get();
+        long cloudPartitionVersionCacheTtlMs = ctx == null
+                ? 
VariableMgr.getDefaultSessionVariable().cloudPartitionVersionCacheTtlMs
+                : ctx.getSessionVariable().cloudPartitionVersionCacheTtlMs;
         if (cloudPartitionVersionCacheTtlMs <= 0) { // No cached versions will 
be used
             return getSnapshotVisibleVersionFromMs(partitions, false);
         }
@@ -345,7 +353,7 @@ public class CloudPartition extends Partition {
     //
     // Return the visible version in order of the specified partition ids
     private static List<Long> getSnapshotVisibleVersion(List<Long> dbIds, 
List<Long> tableIds, List<Long> partitionIds,
-            List<Long> versionUpdateTimesMs, boolean waitForPendingTxns)
+            List<Long> versionUpdateTimesMs, boolean waitForPendingTxns, int 
maxAttempts)
             throws RpcException {
         assert dbIds.size() == partitionIds.size() :
                 "partition ids size: " + partitionIds.size() + " should equals 
to db ids size: " + dbIds.size();
@@ -367,7 +375,7 @@ public class CloudPartition extends Partition {
         if (LOG.isDebugEnabled()) {
             LOG.debug("getVisibleVersion use CloudPartition {}", 
partitionIds.toString());
         }
-        Cloud.GetVersionResponse resp = VersionHelper.getVersionFromMeta(req);
+        Cloud.GetVersionResponse resp = VersionHelper.getVersionFromMeta(req, 
maxAttempts);
         if (resp.getStatus().getCode() != MetaServiceCode.OK) {
             throw new RpcException("get visible version", "unexpected status " 
+ resp.getStatus());
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudSyncVersionDaemon.java
 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudSyncVersionDaemon.java
index d65a6806eac..6d485d959bc 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudSyncVersionDaemon.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/catalog/CloudSyncVersionDaemon.java
@@ -24,6 +24,7 @@ import org.apache.doris.catalog.Partition;
 import org.apache.doris.catalog.Table;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.util.MasterDaemon;
+import org.apache.doris.qe.VariableMgr;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -58,6 +59,13 @@ public class CloudSyncVersionDaemon extends MasterDaemon {
         if (!Config.cloud_enable_version_syncer) {
             return;
         }
+        // This daemon has no ConnectContext, so use the global/default TTLs 
to decide whether
+        // the shared version caches need proactive refresh. Finite TTLs 
refresh lazily on reads,
+        // while Long.MAX_VALUE never expires and requires this daemon to keep 
the cache current.
+        if 
(VariableMgr.getDefaultSessionVariable().cloudPartitionVersionCacheTtlMs != 
Long.MAX_VALUE
+                && 
VariableMgr.getDefaultSessionVariable().cloudTableVersionCacheTtlMs != 
Long.MAX_VALUE) {
+            return;
+        }
         LOG.info("begin sync cloud table and partition version");
         Map<OlapTable, Long> tableVersionMap = syncTableVersions();
         if (!tableVersionMap.isEmpty()) {
@@ -121,7 +129,8 @@ public class CloudSyncVersionDaemon extends MasterDaemon {
             List<Long> tableIds, List<OlapTable> tables) {
         return GET_VERSION_THREAD_POOL.submit(() -> {
             try {
-                List<Long> versions = 
OlapTable.getVisibleVersionFromMeta(dbIds, tableIds);
+                List<Long> versions = OlapTable.getVisibleVersionFromMeta(
+                        dbIds, tableIds, 
Config.cloud_version_syncer_get_version_retry_times);
                 for (int i = 0; i < tables.size(); i++) {
                     OlapTable table = tables.get(i);
                     long version = versions.get(i);
@@ -190,7 +199,8 @@ public class CloudSyncVersionDaemon extends MasterDaemon {
     private Future<Void> submitGetPartitionVersionTask(Set<Long> failedTables, 
List<CloudPartition> partitions) {
         return GET_VERSION_THREAD_POOL.submit(() -> {
             try {
-                CloudPartition.getSnapshotVisibleVersionFromMs(partitions, 
false);
+                CloudPartition.getSnapshotVisibleVersionFromMs(
+                        partitions, false, 
Config.cloud_version_syncer_get_version_retry_times);
             } catch (Exception e) {
                 LOG.warn("get partition version error", e);
                 Set<Long> failedTableIds = partitions.stream().map(p -> 
p.getTableId())
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/rpc/VersionHelper.java 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/rpc/VersionHelper.java
index 703f8d2675c..d0003c50467 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/cloud/rpc/VersionHelper.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/cloud/rpc/VersionHelper.java
@@ -38,10 +38,15 @@ public class VersionHelper {
     // Call get_version() from meta service, and save the elapsed to summary 
profile.
     public static Cloud.GetVersionResponse 
getVersionFromMeta(Cloud.GetVersionRequest req)
             throws RpcException {
+        return getVersionFromMeta(req, Config.metaServiceRpcRetryTimes());
+    }
+
+    public static Cloud.GetVersionResponse 
getVersionFromMeta(Cloud.GetVersionRequest req, int maxAttempts)
+            throws RpcException {
         long startAt = System.nanoTime();
         boolean isTableVersion = req.getIsTableVersion();
         try {
-            return getVisibleVersion(req);
+            return getVisibleVersion(req, maxAttempts);
         } finally {
             SummaryProfile profile = getSummaryProfile();
             if (profile != null) {
@@ -56,8 +61,13 @@ public class VersionHelper {
     }
 
     public static Cloud.GetVersionResponse 
getVisibleVersion(Cloud.GetVersionRequest request) throws RpcException {
+        return getVisibleVersion(request, Config.metaServiceRpcRetryTimes());
+    }
+
+    public static Cloud.GetVersionResponse 
getVisibleVersion(Cloud.GetVersionRequest request, int maxAttempts)
+            throws RpcException {
         int tryTimes = 0;
-        while (tryTimes++ < Config.metaServiceRpcRetryTimes()) {
+        while (tryTimes++ < maxAttempts) {
             Cloud.GetVersionResponse resp = getVisibleVersionInternal(request,
                     Config.default_get_version_from_ms_timeout_second * 1000);
             if (resp != null) {
@@ -73,14 +83,16 @@ public class VersionHelper {
                         resp.getStatus(), tryTimes);
             }
             // sleep random millis, retry rpc failed
-            if (tryTimes > Config.metaServiceRpcRetryTimes() / 2) {
-                sleepSeveralMs(500, 1000);
-            } else {
-                sleepSeveralMs(20, 200);
+            if (tryTimes < maxAttempts) {
+                if (tryTimes > maxAttempts / 2) {
+                    sleepSeveralMs(500, 1000);
+                } else {
+                    sleepSeveralMs(20, 200);
+                }
             }
         }
 
-        LOG.warn("get version from meta service failed after retry {} times", 
tryTimes);
+        LOG.warn("get version from meta service failed after retry {} times", 
maxAttempts);
         throw new RpcException("get version from meta service", "failed after 
retry n times");
     }
 
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/catalog/OlapTableTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/OlapTableTest.java
index 1353ec7ea8b..3a10a7dc162 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/OlapTableTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/OlapTableTest.java
@@ -637,7 +637,7 @@ public class OlapTableTest {
 
         new MockUp<VersionHelper>() {
             @Mock
-            public Cloud.GetVersionResponse 
getVersionFromMeta(Cloud.GetVersionRequest req) {
+            public Cloud.GetVersionResponse 
getVersionFromMeta(Cloud.GetVersionRequest req, int maxAttempts) {
                 Cloud.GetVersionResponse.Builder builder = 
Cloud.GetVersionResponse.newBuilder();
                 builder.setStatus(Cloud.MetaServiceResponseStatus.newBuilder()
                         .setCode(Cloud.MetaServiceCode.OK).build());
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/cloud/catalog/CloudPartitionTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/cloud/catalog/CloudPartitionTest.java
index de01b9a02f5..02d22ddcba8 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/cloud/catalog/CloudPartitionTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/cloud/catalog/CloudPartitionTest.java
@@ -21,6 +21,7 @@ import org.apache.doris.cloud.proto.Cloud;
 import org.apache.doris.cloud.rpc.VersionHelper;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.qe.SessionVariable;
+import org.apache.doris.qe.VariableMgr;
 import org.apache.doris.rpc.RpcException;
 
 import mockit.Mock;
@@ -28,6 +29,8 @@ import mockit.MockUp;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -72,6 +75,29 @@ public class CloudPartitionTest {
 
     }
 
+    @Test
+    public void 
testSnapshotVisibleVersionUsesDefaultCacheTtlWithoutConnectContext() throws 
RpcException {
+        ConnectContext.remove();
+        SessionVariable defaultSessionVariable = 
VariableMgr.getDefaultSessionVariable();
+        long originalCacheTtlMs = 
defaultSessionVariable.cloudPartitionVersionCacheTtlMs;
+        try {
+            defaultSessionVariable.cloudPartitionVersionCacheTtlMs = 
Long.MAX_VALUE;
+            CloudPartition cachedPartition = createPartition(1, 2, 3);
+            cachedPartition.setCachedVisibleVersion(2, 10086L);
+
+            try (MockedStatic<VersionHelper> mockedVersionHelper = 
Mockito.mockStatic(VersionHelper.class)) {
+                List<Long> versions = CloudPartition.getSnapshotVisibleVersion(
+                        Arrays.asList(cachedPartition));
+
+                Assertions.assertEquals(Arrays.asList(2L), versions);
+                mockedVersionHelper.verifyNoInteractions();
+            }
+        } finally {
+            defaultSessionVariable.cloudPartitionVersionCacheTtlMs = 
originalCacheTtlMs;
+            ConnectContext.remove();
+        }
+    }
+
     @Test
     public void testCachedVersion() throws RpcException {
         // Create ConnectContext with SessionVariable
@@ -98,7 +124,7 @@ public class CloudPartitionTest {
 
         new MockUp<VersionHelper>(VersionHelper.class) {
             @Mock
-            public Cloud.GetVersionResponse 
getVersionFromMeta(Cloud.GetVersionRequest req) {
+            public Cloud.GetVersionResponse 
getVersionFromMeta(Cloud.GetVersionRequest req, int maxAttempts) {
                 Cloud.GetVersionResponse.Builder builder = 
Cloud.GetVersionResponse.newBuilder();
                 builder.setVersion(singleVersions.get(callCount[0]));
                 builder.addAllVersions(batchVersions.get(callCount[0]));
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/cloud/rpc/VersionHelperTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/cloud/rpc/VersionHelperTest.java
new file mode 100644
index 00000000000..ffdb81a988f
--- /dev/null
+++ b/fe/fe-core/src/test/java/org/apache/doris/cloud/rpc/VersionHelperTest.java
@@ -0,0 +1,70 @@
+// 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.doris.cloud.rpc;
+
+import org.apache.doris.cloud.proto.Cloud;
+import org.apache.doris.rpc.RpcException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.util.concurrent.CompletableFuture;
+
+public class VersionHelperTest {
+    @Test
+    public void testGetVisibleVersionUsesSpecifiedMaxAttempts() throws 
RpcException {
+        Cloud.GetVersionRequest request = 
Cloud.GetVersionRequest.newBuilder().build();
+        Cloud.GetVersionResponse failedResponse = 
Cloud.GetVersionResponse.newBuilder()
+                .setStatus(Cloud.MetaServiceResponseStatus.newBuilder()
+                        .setCode(Cloud.MetaServiceCode.KV_TXN_GET_ERR))
+                .build();
+        MetaServiceProxy proxy = Mockito.mock(MetaServiceProxy.class);
+        Mockito.when(proxy.getVisibleVersionAsync(request))
+                .thenReturn(CompletableFuture.completedFuture(failedResponse));
+
+        try (MockedStatic<MetaServiceProxy> mockedProxy = 
Mockito.mockStatic(MetaServiceProxy.class)) {
+            mockedProxy.when(MetaServiceProxy::getInstance).thenReturn(proxy);
+
+            Assert.assertThrows(RpcException.class, () -> 
VersionHelper.getVisibleVersion(request, 3));
+        }
+
+        Mockito.verify(proxy, 
Mockito.times(3)).getVisibleVersionAsync(request);
+    }
+
+    @Test
+    public void testGetVisibleVersionStopsOnVersionNotFound() throws 
RpcException {
+        Cloud.GetVersionRequest request = 
Cloud.GetVersionRequest.newBuilder().build();
+        Cloud.GetVersionResponse notFoundResponse = 
Cloud.GetVersionResponse.newBuilder()
+                .setStatus(Cloud.MetaServiceResponseStatus.newBuilder()
+                        .setCode(Cloud.MetaServiceCode.VERSION_NOT_FOUND))
+                .build();
+        MetaServiceProxy proxy = Mockito.mock(MetaServiceProxy.class);
+        Mockito.when(proxy.getVisibleVersionAsync(request))
+                
.thenReturn(CompletableFuture.completedFuture(notFoundResponse));
+
+        try (MockedStatic<MetaServiceProxy> mockedProxy = 
Mockito.mockStatic(MetaServiceProxy.class)) {
+            mockedProxy.when(MetaServiceProxy::getInstance).thenReturn(proxy);
+
+            Assert.assertSame(notFoundResponse, 
VersionHelper.getVisibleVersion(request, 3));
+        }
+
+        Mockito.verify(proxy).getVisibleVersionAsync(request);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to