Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.2k
[RTO/RPO] Topology awareness for query plan#15014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
6ea3c1549a0c15a9e1384e16688d2b622b1d2f0451ebfbdf84e418fbb9d5cc5cb3ad7e055e69684f5d337d065f7e844034f3832c2d91ae734bb12fc810753c044e9c7File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -20,12 +20,14 @@ | ||
| package org.apache.iotdb.db.it.utils; | ||
| import org.apache.iotdb.commons.auth.entity.PrivilegeType; | ||
| import org.apache.iotdb.commons.cluster.NodeStatus; | ||
| import org.apache.iotdb.isession.SessionConfig; | ||
| import org.apache.iotdb.isession.SessionDataSet; | ||
| import org.apache.iotdb.it.env.EnvFactory; | ||
| import org.apache.iotdb.it.env.cluster.env.AbstractEnv; | ||
| import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper; | ||
| import org.apache.iotdb.itbase.env.BaseEnv; | ||
| import org.apache.iotdb.itbase.env.BaseNodeWrapper; | ||
| import org.apache.iotdb.rpc.IoTDBConnectionException; | ||
| import org.apache.iotdb.rpc.RpcUtils; | ||
| import org.apache.iotdb.rpc.StatementExecutionException; | ||
| @@ -43,6 +45,7 @@ | ||
| import java.text.DateFormat; | ||
| import java.time.ZoneId; | ||
| import java.time.ZoneOffset; | ||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.HashMap; | ||
| import java.util.HashSet; | ||
| @@ -1706,6 +1709,11 @@ public static void restartDataNodes() { | ||
| long retryIntervalMS = 1000; | ||
| while (true) { | ||
| try (Connection connection = EnvFactory.getEnv().getConnection()) { | ||
| final List<BaseNodeWrapper> allDataNodes = | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this in next PR | ||
| new ArrayList<>(EnvFactory.getEnv().getDataNodeWrapperList()); | ||
| EnvFactory.getEnv() | ||
| .ensureNodeStatus( | ||
| allDataNodes, Collections.nCopies(allDataNodes.size(), NodeStatus.Running)); | ||
| break; | ||
| } catch (Exception e) { | ||
| try { | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -49,12 +49,15 @@ | ||
| import org.apache.iotdb.confignode.manager.load.cache.region.RegionStatistics; | ||
| import org.apache.iotdb.confignode.manager.partition.RegionGroupStatus; | ||
| import org.apache.thrift.annotation.Nullable; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.Comparator; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| @@ -94,6 +97,8 @@ public class LoadCache { | ||
| private final Map<TConsensusGroupId, ConsensusGroupCache> consensusGroupCacheMap; | ||
| // Map<DataNodeId, confirmedConfigNodes> | ||
| private final Map<Integer, Set<TEndPoint>> confirmedConfigNodeMap; | ||
| private Map<Integer, Set<Integer>> topologyGraph; | ||
| private final AtomicBoolean topologyUpdated; | ||
| public LoadCache() { | ||
| this.nodeCacheMap = new ConcurrentHashMap<>(); | ||
| @@ -102,6 +107,8 @@ public LoadCache() { | ||
| this.regionSizeMap = new ConcurrentHashMap<>(); | ||
| this.consensusGroupCacheMap = new ConcurrentHashMap<>(); | ||
| this.confirmedConfigNodeMap = new ConcurrentHashMap<>(); | ||
| this.topologyGraph = new HashMap<>(); | ||
| this.topologyUpdated = new AtomicBoolean(false); | ||
| } | ||
| public void initHeartbeatCache(final IManager configManager) { | ||
| @@ -175,6 +182,7 @@ private void initRegionGroupHeartbeatCache( | ||
| regionGroupId, | ||
| new RegionGroupCache( | ||
| database, | ||
| regionGroupId, | ||
| regionReplicaSet.getDataNodeLocations().stream() | ||
| .map(TDataNodeLocation::getDataNodeId) | ||
| .collect(Collectors.toSet()), | ||
| @@ -287,7 +295,8 @@ public void createRegionGroupHeartbeatCache( | ||
| String database, TConsensusGroupId regionGroupId, Set<Integer> dataNodeIds) { | ||
| boolean isStrongConsistency = CONF.isConsensusGroupStrongConsistency(regionGroupId); | ||
| regionGroupCacheMap.put( | ||
| regionGroupId, new RegionGroupCache(database, dataNodeIds, isStrongConsistency)); | ||
| regionGroupId, | ||
| new RegionGroupCache(database, regionGroupId, dataNodeIds, isStrongConsistency)); | ||
| consensusGroupCacheMap.put(regionGroupId, new ConsensusGroupCache()); | ||
| } | ||
| @@ -299,7 +308,7 @@ public void createRegionGroupHeartbeatCache( | ||
| */ | ||
| public void createRegionCache(TConsensusGroupId regionGroupId, int dataNodeId) { | ||
| Optional.ofNullable(regionGroupCacheMap.get(regionGroupId)) | ||
| .ifPresent(cache -> cache.createRegionCache(dataNodeId)); | ||
| .ifPresent(cache -> cache.createRegionCache(dataNodeId, regionGroupId)); | ||
| } | ||
| /** | ||
| @@ -769,6 +778,22 @@ public void waitForLeaderElection(List<TConsensusGroupId> regionGroupIds) { | ||
| regionGroupIds); | ||
| } | ||
| public void updateTopology(Map<Integer, Set<Integer>> latestTopology) { | ||
| if (!latestTopology.equals(topologyGraph)) { | ||
| LOGGER.info("[Topology Service] Cluster topology changed, latest: {}", latestTopology); | ||
| } | ||
| topologyGraph = latestTopology; | ||
| topologyUpdated.set(true); | ||
| } | ||
| @Nullable | ||
| public Map<Integer, Set<Integer>> getTopology() { | ||
SzyWilliam marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if (topologyUpdated.compareAndSet(true, false)) { | ||
| return Collections.unmodifiableMap(topologyGraph); | ||
| } | ||
| return null; | ||
| } | ||
| public void updateConfirmedConfigNodeEndPoints( | ||
| int dataNodeId, Set<TEndPoint> configNodeEndPoints) { | ||
| confirmedConfigNodeMap.put(dataNodeId, configNodeEndPoints); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -24,13 +24,16 @@ | ||
| import org.apache.iotdb.confignode.manager.load.cache.node.NodeHeartbeatSample; | ||
| import org.apache.iotdb.confignode.manager.load.cache.region.RegionHeartbeatSample; | ||
| import com.google.common.cache.Cache; | ||
| import com.google.common.cache.CacheBuilder; | ||
| import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; | ||
| import org.apache.tsfile.utils.Preconditions; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.concurrent.TimeUnit; | ||
| /** | ||
| * The Phi Failure Detector, proposed by Hayashibara, Naohiro, et al. "The/spl phi/accrual failure | ||
| @@ -49,6 +52,8 @@ public class PhiAccrualDetector implements IFailureDetector { | ||
| private final long minHeartbeatStdNs; | ||
| private final int codeStartSampleCount; | ||
| private final IFailureDetector fallbackDuringColdStart; | ||
| /* We are using cache here to avoid managing entry life cycles manually */ | ||
| private final Cache<Object, Boolean> availibilityCache; | ||
| public PhiAccrualDetector( | ||
| long threshold, | ||
| @@ -61,17 +66,23 @@ public PhiAccrualDetector( | ||
| this.minHeartbeatStdNs = minHeartbeatStdNs; | ||
| this.codeStartSampleCount = minimalSampleCount; | ||
| this.fallbackDuringColdStart = fallbackDuringColdStart; | ||
| this.availibilityCache = | ||
SzyWilliam marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build(); | ||
| } | ||
| @Override | ||
| public boolean isAvailable(List<AbstractHeartbeatSample> history) { | ||
| public boolean isAvailable(Object id, List<AbstractHeartbeatSample> history) { | ||
| if (history.size() < codeStartSampleCount) { | ||
| /* We haven't received enough heartbeat replies.*/ | ||
| return fallbackDuringColdStart.isAvailable(history); | ||
| return fallbackDuringColdStart.isAvailable(id, history); | ||
| } | ||
| final PhiAccrual phiAccrual = create(history); | ||
| final boolean isAvailable = phiAccrual.phi() < (double) this.threshold; | ||
| if (!isAvailable && LOGGER.isDebugEnabled()) { | ||
| final Boolean previousAvailability = availibilityCache.getIfPresent(id); | ||
| availibilityCache.put(id, isAvailable); | ||
| if (Boolean.TRUE.equals(previousAvailability) && !isAvailable) { | ||
| // log the status change and dump the heartbeat history for analysis use | ||
| final StringBuilder builder = new StringBuilder(); | ||
| builder.append("["); | ||
| @@ -81,7 +92,7 @@ public boolean isAvailable(List<AbstractHeartbeatSample> history) { | ||
| } | ||
| builder.append(phiAccrual.timeElapsedSinceLastHeartbeat / 1000_000); | ||
| builder.append("]"); | ||
| LOGGER.debug(String.format("Node Down, heartbeat history (ms): %s", builder)); | ||
| LOGGER.info(String.format("Node Down, heartbeat history (ms): %s", builder)); | ||
| } | ||
| return isAvailable; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -19,10 +19,13 @@ | ||
| package org.apache.iotdb.confignode.manager.load.cache.region; | ||
| import org.apache.iotdb.common.rpc.thrift.TConsensusGroupId; | ||
| import org.apache.iotdb.commons.cluster.RegionStatus; | ||
| import org.apache.iotdb.confignode.manager.load.cache.AbstractHeartbeatSample; | ||
| import org.apache.iotdb.confignode.manager.load.cache.AbstractLoadCache; | ||
| import org.apache.tsfile.utils.Pair; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| @@ -31,9 +34,11 @@ | ||
| * statistics of the Region based on the latest RegionHeartbeatSample. | ||
| */ | ||
| public class RegionCache extends AbstractLoadCache { | ||
| private final Pair<Integer, TConsensusGroupId> id; | ||
| public RegionCache() { | ||
| public RegionCache(int dataNodeId, TConsensusGroupId gid) { | ||
| super(); | ||
| this.id = new Pair<>(dataNodeId, gid); | ||
| this.currentStatistics.set(RegionStatistics.generateDefaultRegionStatistics()); | ||
| } | ||
| @@ -50,7 +55,7 @@ public synchronized void updateCurrentStatistics(boolean forceUpdate) { | ||
| if (lastSample == null) { | ||
| /* First heartbeat not received from this region, status is UNKNOWN */ | ||
| status = RegionStatus.Unknown; | ||
| } else if (!failureDetector.isAvailable(history)) { | ||
SzyWilliam marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } else if (!failureDetector.isAvailable(id, history)) { | ||
| /* Failure detector decides that this region is UNKNOWN */ | ||
| status = RegionStatus.Unknown; | ||
| } else { | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.