未验证 提交 250d4a5a 编写于 作者: J Juan Pan(Trista) 提交者: GitHub

Handle the out of bounds case for StandardRangeShardingAlgorithm (#5998)

上级 de385f34
...@@ -40,7 +40,8 @@ import java.util.Properties; ...@@ -40,7 +40,8 @@ import java.util.Properties;
* *
* <p>Shard by `y = floor(x/v)` algorithm, which means y begins from 0. * <p>Shard by `y = floor(x/v)` algorithm, which means y begins from 0.
* v is `PARTITION_SECONDS`, and the minimum time unit is 1 sec. * v is `PARTITION_SECONDS`, and the minimum time unit is 1 sec.
* `EPOCH` decides the beginning datetime to shard. </p> * `DATETIME_LOWER` decides the beginning datetime to shard. On the other hand, `DATETIME_UPPER` decides the end datetime to shard.</p>
* <p>Notice: Anytime less then `DATETIME_LOWER` will route to the first partition, and anytime great than `DATETIME_UPPER` will route to the last partition.</p>
*/ */
public final class DatetimeShardingAlgorithm implements StandardShardingAlgorithm<Comparable<?>>, ShardingAutoTableAlgorithm { public final class DatetimeShardingAlgorithm implements StandardShardingAlgorithm<Comparable<?>>, ShardingAutoTableAlgorithm {
......
...@@ -58,9 +58,9 @@ public abstract class AbstractRangeShardingAlgorithm implements StandardSharding ...@@ -58,9 +58,9 @@ public abstract class AbstractRangeShardingAlgorithm implements StandardSharding
@Override @Override
public final Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Long> shardingValue) { public final Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size()); Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
int lowerEndpointPartition = getPartition(partitionRangeMap, shardingValue.getValueRange().lowerEndpoint()); int firstPartition = getFirstPartition(shardingValue.getValueRange());
int upperEndpointPartition = getPartition(partitionRangeMap, shardingValue.getValueRange().upperEndpoint()); int lastPartition = getLastPartition(shardingValue.getValueRange());
for (int partition = lowerEndpointPartition; partition <= upperEndpointPartition; partition++) { for (int partition = firstPartition; partition <= lastPartition; partition++) {
for (String each : availableTargetNames) { for (String each : availableTargetNames) {
if (each.endsWith(partition + "")) { if (each.endsWith(partition + "")) {
result.add(each); result.add(each);
...@@ -70,6 +70,14 @@ public abstract class AbstractRangeShardingAlgorithm implements StandardSharding ...@@ -70,6 +70,14 @@ public abstract class AbstractRangeShardingAlgorithm implements StandardSharding
return result; return result;
} }
private int getFirstPartition(final Range<Long> valueRange) {
return valueRange.hasLowerBound() ? getPartition(partitionRangeMap, valueRange.lowerEndpoint()) : 0;
}
private int getLastPartition(final Range<Long> valueRange) {
return valueRange.hasUpperBound() ? getPartition(partitionRangeMap, valueRange.upperEndpoint()) : partitionRangeMap.size() - 1;
}
private Integer getPartition(final Map<Integer, Range<Long>> partitionRangeMap, final Long value) { private Integer getPartition(final Map<Integer, Range<Long>> partitionRangeMap, final Long value) {
for (Entry<Integer, Range<Long>> entry : partitionRangeMap.entrySet()) { for (Entry<Integer, Range<Long>> entry : partitionRangeMap.entrySet()) {
if (entry.getValue().contains(value)) { if (entry.getValue().contains(value)) {
......
...@@ -31,20 +31,20 @@ import java.util.Properties; ...@@ -31,20 +31,20 @@ import java.util.Properties;
* *
* <p> * <p>
* Standard range sharding algorithm is similar to the rule of partition table, but it can only be split by the same size. * Standard range sharding algorithm is similar to the rule of partition table, but it can only be split by the same size.
* User can specify the range by setting `partition.lower`, `partition.upper` and `partition.volume` parameters. * User can specify the range by setting `range.lower`, `range.upper` and `partition.volume` parameters.
* The `partition.volume` parameter determines the size of each partition. * The `partition.volume` parameter determines the size of each partition.
* </p> * </p>
* <p> * <p>
* For example: If the `partition.lower` parameter is set to `10`, the `partition.upper` parameter is set to `45`, * For example: If the `range.lower` parameter is set to `10`, the `range.upper` parameter is set to `45`,
* and the `partition.volume` parameter is set to `10`. The values in range [10,45] will be split to different partitions * and the `partition.volume` parameter is set to `10`. The values in range [10,45] will be split to different partitions
* ——[10,20), [20, 30), [30, 40), [40, 45), and other values will be split to (-∞, 10) and [45, +∞). * ——[10,20), [20, 30), [30, 40), [40, 45), and other values will be split to (-∞, 10) and [45, +∞).
* </p> * </p>
*/ */
public final class StandardRangeShardingAlgorithm extends AbstractRangeShardingAlgorithm { public final class StandardRangeShardingAlgorithm extends AbstractRangeShardingAlgorithm {
private static final String PARTITION_LOWER = "partition.lower"; private static final String RANGE_LOWER = "range.lower";
private static final String PARTITION_UPPER = "partition.upper"; private static final String RANGE_UPPER = "range.upper";
private static final String PARTITION_VOLUME = "partition.volume"; private static final String PARTITION_VOLUME = "partition.volume";
...@@ -55,11 +55,11 @@ public final class StandardRangeShardingAlgorithm extends AbstractRangeShardingA ...@@ -55,11 +55,11 @@ public final class StandardRangeShardingAlgorithm extends AbstractRangeShardingA
@Override @Override
public Map<Integer, Range<Long>> createPartitionRangeMap(final Properties properties) { public Map<Integer, Range<Long>> createPartitionRangeMap(final Properties properties) {
Preconditions.checkNotNull(properties.get(PARTITION_LOWER), "Standard range sharding algorithm partition lower cannot be null."); Preconditions.checkNotNull(properties.get(RANGE_LOWER), "Standard range sharding algorithm partition lower cannot be null.");
Preconditions.checkNotNull(properties.get(PARTITION_UPPER), "Standard range sharding algorithm partition upper cannot be null."); Preconditions.checkNotNull(properties.get(RANGE_UPPER), "Standard range sharding algorithm partition upper cannot be null.");
Preconditions.checkNotNull(properties.get(PARTITION_VOLUME), "Standard range sharding algorithm partition volume cannot be null."); Preconditions.checkNotNull(properties.get(PARTITION_VOLUME), "Standard range sharding algorithm partition volume cannot be null.");
long lower = Long.parseLong(properties.get(PARTITION_LOWER).toString()); long lower = Long.parseLong(properties.get(RANGE_LOWER).toString());
long upper = Long.parseLong(properties.get(PARTITION_UPPER).toString()); long upper = Long.parseLong(properties.get(RANGE_UPPER).toString());
long volume = Long.parseLong(properties.get(PARTITION_VOLUME).toString()); long volume = Long.parseLong(properties.get(PARTITION_VOLUME).toString());
Preconditions.checkArgument(upper - lower >= volume, "Standard range sharding algorithm partition range can not be smaller than volume."); Preconditions.checkArgument(upper - lower >= volume, "Standard range sharding algorithm partition range can not be smaller than volume.");
int partitionSize = Math.toIntExact(LongMath.divide(upper - lower, volume, RoundingMode.CEILING)); int partitionSize = Math.toIntExact(LongMath.divide(upper - lower, volume, RoundingMode.CEILING));
......
...@@ -104,7 +104,7 @@ public final class DatetimeShardingAlgorithmTest { ...@@ -104,7 +104,7 @@ public final class DatetimeShardingAlgorithmTest {
} }
@Test @Test
public void assertPreciseDoShardingWithoutLowerBound() { public void assertRangeDoShardingWithoutLowerBound() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3"); List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3");
Range<String> rangeValue = Range.lessThan("2020-01-01 00:00:11"); Range<String> rangeValue = Range.lessThan("2020-01-01 00:00:11");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue)); List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue));
...@@ -117,7 +117,7 @@ public final class DatetimeShardingAlgorithmTest { ...@@ -117,7 +117,7 @@ public final class DatetimeShardingAlgorithmTest {
} }
@Test @Test
public void assertPreciseDoShardingWithoutUpperBound() { public void assertRangeDoShardingWithoutUpperBound() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3", "t_order_4", "t_order_5"); List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3", "t_order_4", "t_order_5");
Range<String> rangeValue = Range.greaterThan("2020-01-01 00:00:09"); Range<String> rangeValue = Range.greaterThan("2020-01-01 00:00:09");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue)); List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue));
......
...@@ -43,8 +43,8 @@ public final class StandardRangeShardingAlgorithmTest { ...@@ -43,8 +43,8 @@ public final class StandardRangeShardingAlgorithmTest {
@Before @Before
public void setUp() { public void setUp() {
StandardRangeShardingAlgorithm shardingAlgorithm = new StandardRangeShardingAlgorithm(); StandardRangeShardingAlgorithm shardingAlgorithm = new StandardRangeShardingAlgorithm();
shardingAlgorithm.getProperties().setProperty("partition.lower", "10"); shardingAlgorithm.getProperties().setProperty("range.lower", "10");
shardingAlgorithm.getProperties().setProperty("partition.upper", "45"); shardingAlgorithm.getProperties().setProperty("range.upper", "45");
shardingAlgorithm.getProperties().setProperty("partition.volume", "10"); shardingAlgorithm.getProperties().setProperty("partition.volume", "10");
shardingAlgorithm.init(); shardingAlgorithm.init();
StandardShardingStrategyConfiguration shardingStrategyConfig = new StandardShardingStrategyConfiguration("order_id", shardingAlgorithm); StandardShardingStrategyConfiguration shardingStrategyConfig = new StandardShardingStrategyConfiguration("order_id", shardingAlgorithm);
...@@ -62,6 +62,26 @@ public final class StandardRangeShardingAlgorithmTest { ...@@ -62,6 +62,26 @@ public final class StandardRangeShardingAlgorithmTest {
assertTrue(actual.contains("t_order_2")); assertTrue(actual.contains("t_order_2"));
assertTrue(actual.contains("t_order_5")); assertTrue(actual.contains("t_order_5"));
} }
@Test
public void assertRangeDoShardingWithoutLowerBound() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3", "t_order_4", "t_order_5");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("order_id", "t_order", Range.lessThan(12L)));
Collection<String> actual = shardingStrategy.doSharding(availableTargetNames, shardingValues, new ConfigurationProperties(new Properties()));
assertThat(actual.size(), is(2));
assertTrue(actual.contains("t_order_0"));
assertTrue(actual.contains("t_order_1"));
}
@Test
public void assertRangeDoShardingWithoutUpperBound() {
List<String> availableTargetNames = Lists.newArrayList("t_order_0", "t_order_1", "t_order_2", "t_order_3", "t_order_4", "t_order_5");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("order_id", "t_order", Range.greaterThan(40L)));
Collection<String> actual = shardingStrategy.doSharding(availableTargetNames, shardingValues, new ConfigurationProperties(new Properties()));
assertThat(actual.size(), is(2));
assertTrue(actual.contains("t_order_4"));
assertTrue(actual.contains("t_order_5"));
}
@Test @Test
public void assertRangeDoSharding() { public void assertRangeDoSharding() {
...@@ -79,8 +99,8 @@ public final class StandardRangeShardingAlgorithmTest { ...@@ -79,8 +99,8 @@ public final class StandardRangeShardingAlgorithmTest {
@Test @Test
public void assertGetAutoTablesAmount() { public void assertGetAutoTablesAmount() {
StandardRangeShardingAlgorithm shardingAlgorithm = new StandardRangeShardingAlgorithm(); StandardRangeShardingAlgorithm shardingAlgorithm = new StandardRangeShardingAlgorithm();
shardingAlgorithm.getProperties().setProperty("partition.lower", "10"); shardingAlgorithm.getProperties().setProperty("range.lower", "10");
shardingAlgorithm.getProperties().setProperty("partition.upper", "45"); shardingAlgorithm.getProperties().setProperty("range.upper", "45");
shardingAlgorithm.getProperties().setProperty("partition.volume", "10"); shardingAlgorithm.getProperties().setProperty("partition.volume", "10");
shardingAlgorithm.init(); shardingAlgorithm.init();
assertThat(shardingAlgorithm.getAutoTablesAmount(), is(6)); assertThat(shardingAlgorithm.getAutoTablesAmount(), is(6));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册