-
Notifications
You must be signed in to change notification settings - Fork 1.9k
IGNITE-26580 Implement an affinity backup filter spreading partition copies to all data centers #12459
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
Merged
sergey-chugunov-1985
merged 24 commits into
apache:master
from
sergey-chugunov-1985:ignite-26580
Nov 11, 2025
Merged
IGNITE-26580 Implement an affinity backup filter spreading partition copies to all data centers #12459
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
d4147bc
IGNITE-26580 Add a preform of a new DC-aware filter and ideas how to …
sergey-chugunov-1985 d1803fa
IGNITE-24580 Backup Filter implementation
sergey-chugunov-1985 7d34a24
IGNITE-24580 Implement happy-case and preform of a test
sergey-chugunov-1985 9ec8010
IGNITE-26580 Test WIP
sergey-chugunov-1985 5bdf0d8
IGNITE-26580 Finish test, fix bug in an MDC filter
sergey-chugunov-1985 b0f1bf0
IGNITE-26580 Add documentation for MDC affinity backup filter
sergey-chugunov-1985 5815442
IGNITE-26580 Include new test to a test suite
sergey-chugunov-1985 cfcf39a
IGNITE-26580 Improve code after self-review
sergey-chugunov-1985 2e8c397
IGNITE-26580 Improve code after self-review
sergey-chugunov-1985 bc0ab84
IGNITE-26580 Address review comments
sergey-chugunov-1985 c2ad25b
IGNITE-26580 Address review comments
sergey-chugunov-1985 cd4fb23
IGNITE-26580 Improve tests
sergey-chugunov-1985 9b34257
IGNITE-26580 Provide proper implementation for hashCode
sergey-chugunov-1985 a65c860
IGNITE-26580 Add test for stability of partition distribution
sergey-chugunov-1985 b68f315
IGNITE-26580 Fix checkstyle issues
sergey-chugunov-1985 988de1a
IGNITE-26580 Add test for baseline
sergey-chugunov-1985 e425013
IGNITE-26580 Fix tests
sergey-chugunov-1985 c85be9f
IGNITE-26580 Fix checkstyle
sergey-chugunov-1985 9c3d0ff
IGNITE-26580 Cleanup system property after test
sergey-chugunov-1985 67ef506
IGNITE-26580 Remove equals-based validation from AffinityBackupFilter…
sergey-chugunov-1985 269835d
IGNITE-26580 Adapt test checks to stripped down validation
sergey-chugunov-1985 09ebf1d
IGNITE-26580 Remove validation for affinity backup filter class as it…
sergey-chugunov-1985 63232c1
IGNITE-26580 Ignore validation test until proper validation is implem…
sergey-chugunov-1985 5fd9842
IGNITE-26580 Remove unused methods
sergey-chugunov-1985 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
128 changes: 128 additions & 0 deletions
128
...re/src/main/java/org/apache/ignite/cache/affinity/rendezvous/MdcAffinityBackupFilter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| /* | ||
| * 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.ignite.cache.affinity.rendezvous; | ||
|
|
||
| import java.util.List; | ||
| import org.apache.ignite.cluster.ClusterNode; | ||
| import org.apache.ignite.internal.util.typedef.internal.S; | ||
| import org.apache.ignite.lang.IgniteBiPredicate; | ||
|
|
||
| /** | ||
| * Multi-data center affinity backup filter that ensures each partition's data is distributed across multiple data centers, | ||
| * providing high availability and fault tolerance. This implementation guarantees at least one copy of the data in each | ||
| * data center and attempts to maintain the configured backup factor without discarding copies. | ||
| * <p> | ||
| * The filter works by grouping nodes based on their data center identification attribute (@see {@link ClusterNode#dataCenterId()}) | ||
| * and ensuring that for every partition, at least one node from each data center is included in the primary-backup set. | ||
| * <p> | ||
| * The filter will discard backup copies only if the number of available nodes in a given data center is less | ||
| * than the number of copies assigned to that data center. | ||
| * For example, if a partition has 4 copies (1 primary and 3 backups) and the cluster has 2 data centers, | ||
| * than 2 copies are assigned to each data center. The only scenario when just a single copy is assigned to a node in a data center is when | ||
| * the number of nodes in that data center is one. | ||
| * <p> | ||
| * This class is constructed with a number of data centers the cluster spans and a number of backups of the cache this filter is applied to. | ||
| * Implementation expects that all copies can be spread evenly across all data centers. In other words, (backups + 1) is divisible by | ||
| * number of data centers without remainder. Uneven distributions of copies are not supported. | ||
| * <p> | ||
| * Warning: Ensure that all nodes have a consistent and valid data center identifier attribute. Missing or inconsistent values | ||
| * may lead to unexpected placement of data. | ||
| * </pre> | ||
| * <h2 class="header">Spring Example</h2> | ||
| * Create a partitioned cache template where each data center has at least one copy of the data, and the backup count is maintained. | ||
| * <pre name="code" class="xml"> | ||
| * <property name="cacheConfiguration"> | ||
| * <list> | ||
| * <bean id="cache-template-bean" abstract="true" class="org.apache.ignite.configuration.CacheConfiguration"> | ||
| * <property name="name" value="JobcaseDefaultCacheConfig*"/> | ||
| * <property name="cacheMode" value="PARTITIONED" /> | ||
| * <property name="backups" value="3" /> | ||
| * <property name="affinity"> | ||
| * <bean class="org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction"> | ||
| * <property name="affinityBackupFilter"> | ||
| * <bean class="org.apache.ignite.cache.affinity.rendezvous.MdcAffinityBackupFilter"> | ||
| * <constructor-arg value="2"/> <!-- dcsNumber --> | ||
| * <constructor-arg value="3"/> <!-- backups, the same as in the cache template --> | ||
| * </bean> | ||
| * </property> | ||
| * </bean> | ||
| * </property> | ||
| * </bean> | ||
| * </list> | ||
| * </property> | ||
| * </pre> | ||
| * <p> | ||
| * With more backups, additional replicas can be distributed across different data centers to further improve redundancy. | ||
| */ | ||
| public class MdcAffinityBackupFilter implements IgniteBiPredicate<ClusterNode, List<ClusterNode>> { | ||
| /** */ | ||
| private static final long serialVersionUID = 1L; | ||
|
|
||
| /** */ | ||
| private final int partCopiesPerDc; | ||
|
|
||
| /** | ||
| * @param dcsNum Number of data centers. | ||
| * @param backups Number of backups. | ||
| */ | ||
| public MdcAffinityBackupFilter(int dcsNum, int backups) { | ||
| if (dcsNum < 2) { | ||
| throw new IllegalArgumentException("MdcAffinityBackupFilter cannot be used in an environment with only one datacenter. " + | ||
| "Number of datacenters must be at least 2."); | ||
| } | ||
|
|
||
| int numCopies = backups + 1; | ||
|
|
||
| partCopiesPerDc = numCopies / dcsNum; | ||
| int remainder = numCopies % dcsNum; | ||
|
|
||
| if (remainder != 0) { | ||
| String suggestion = "recommended "; | ||
| if (numCopies - remainder <= 0) | ||
| suggestion += "value is " + (backups + (dcsNum - remainder)); | ||
| else | ||
| suggestion += "values are " + (backups - remainder) + " and " + (backups + (dcsNum - remainder)); | ||
|
|
||
| throw new IllegalArgumentException("Number of copies is not completely divisible by number of datacenters, " + | ||
| "copies cannot be distributed evenly across DCs. " + | ||
| "Please adjust the number of backups, " + suggestion); | ||
| } | ||
|
sergey-chugunov-1985 marked this conversation as resolved.
|
||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override public boolean apply(ClusterNode candidate, List<ClusterNode> previouslySelected) { | ||
| String candidateDcId = candidate.dataCenterId(); | ||
| int candDcCopiesAssigned = 0; | ||
|
|
||
| for (int i = 0; i < previouslySelected.size(); i++) { | ||
| String prevDcId = previouslySelected.get(i).dataCenterId(); | ||
|
|
||
| if (prevDcId == null) | ||
| return false; | ||
|
sergey-chugunov-1985 marked this conversation as resolved.
|
||
|
|
||
| candDcCopiesAssigned += prevDcId.equals(candidateDcId) ? 1 : 0; | ||
| } | ||
|
|
||
| return candDcCopiesAssigned < partCopiesPerDc; | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override public String toString() { | ||
| return S.toString(MdcAffinityBackupFilter.class, this); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.