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

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

上级 de385f34
......@@ -40,7 +40,8 @@ import java.util.Properties;
*
* <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.
* `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 {
......
......@@ -58,9 +58,9 @@ public abstract class AbstractRangeShardingAlgorithm implements StandardSharding
@Override
public final Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
int lowerEndpointPartition = getPartition(partitionRangeMap, shardingValue.getValueRange().lowerEndpoint());
int upperEndpointPartition = getPartition(partitionRangeMap, shardingValue.getValueRange().upperEndpoint());
for (int partition = lowerEndpointPartition; partition <= upperEndpointPartition; partition++) {
int firstPartition = getFirstPartition(shardingValue.getValueRange());
int lastPartition = getLastPartition(shardingValue.getValueRange());
for (int partition = firstPartition; partition <= lastPartition; partition++) {
for (String each : availableTargetNames) {
if (each.endsWith(partition + "")) {
result.add(each);
......@@ -70,6 +70,14 @@ public abstract class AbstractRangeShardingAlgorithm implements StandardSharding
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) {
for (Entry<Integer, Range<Long>> entry : partitionRangeMap.entrySet()) {
if (entry.getValue().contains(value)) {
......
......@@ -31,20 +31,20 @@ import java.util.Properties;
*
* <p>
* 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.
* </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
* ——[10,20), [20, 30), [30, 40), [40, 45), and other values will be split to (-∞, 10) and [45, +∞).
* </p>
*/
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";
......@@ -55,11 +55,11 @@ public final class StandardRangeShardingAlgorithm extends AbstractRangeShardingA
@Override
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(PARTITION_UPPER), "Standard range sharding algorithm partition upper cannot be null.");
Preconditions.checkNotNull(properties.get(RANGE_LOWER), "Standard range sharding algorithm partition lower 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.");
long lower = Long.parseLong(properties.get(PARTITION_LOWER).toString());
long upper = Long.parseLong(properties.get(PARTITION_UPPER).toString());
long lower = Long.parseLong(properties.get(RANGE_LOWER).toString());
long upper = Long.parseLong(properties.get(RANGE_UPPER).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.");
int partitionSize = Math.toIntExact(LongMath.divide(upper - lower, volume, RoundingMode.CEILING));
......
......@@ -104,7 +104,7 @@ public final class DatetimeShardingAlgorithmTest {
}
@Test
public void assertPreciseDoShardingWithoutLowerBound() {
public void assertRangeDoShardingWithoutLowerBound() {
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");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue));
......@@ -117,7 +117,7 @@ public final class DatetimeShardingAlgorithmTest {
}
@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");
Range<String> rangeValue = Range.greaterThan("2020-01-01 00:00:09");
List<RouteValue> shardingValues = Lists.newArrayList(new RangeRouteValue<>("create_time", "t_order", rangeValue));
......
......@@ -43,8 +43,8 @@ public final class StandardRangeShardingAlgorithmTest {
@Before
public void setUp() {
StandardRangeShardingAlgorithm shardingAlgorithm = new StandardRangeShardingAlgorithm();
shardingAlgorithm.getProperties().setProperty("partition.lower", "10");
shardingAlgorithm.getProperties().setProperty("partition.upper", "45");
shardingAlgorithm.getProperties().setProperty("range.lower", "10");
shardingAlgorithm.getProperties().setProperty("range.upper", "45");
shardingAlgorithm.getProperties().setProperty("partition.volume", "10");
shardingAlgorithm.init();
StandardShardingStrategyConfiguration shardingStrategyConfig = new StandardShardingStrategyConfiguration("order_id", shardingAlgorithm);
......@@ -62,6 +62,26 @@ public final class StandardRangeShardingAlgorithmTest {
assertTrue(actual.contains("t_order_2"));
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
public void assertRangeDoSharding() {
......@@ -79,8 +99,8 @@ public final class StandardRangeShardingAlgorithmTest {
@Test
public void assertGetAutoTablesAmount() {
StandardRangeShardingAlgorithm shardingAlgorithm = new StandardRangeShardingAlgorithm();
shardingAlgorithm.getProperties().setProperty("partition.lower", "10");
shardingAlgorithm.getProperties().setProperty("partition.upper", "45");
shardingAlgorithm.getProperties().setProperty("range.lower", "10");
shardingAlgorithm.getProperties().setProperty("range.upper", "45");
shardingAlgorithm.getProperties().setProperty("partition.volume", "10");
shardingAlgorithm.init();
assertThat(shardingAlgorithm.getAutoTablesAmount(), is(6));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册