Sharding Pattern (#1056)
* Create sharding module * Add Unit Tests * Fix readme hyperlink * Fix check-style issue
This commit is contained in:
parent
50986fa15b
commit
1fa8a604eb
1
pom.xml
1
pom.xml
@ -184,6 +184,7 @@
|
||||
<module>subclass-sandbox</module>
|
||||
<module>circuit-breaker</module>
|
||||
<module>double-buffer</module>
|
||||
<module>sharding</module>
|
||||
</modules>
|
||||
|
||||
<repositories>
|
||||
|
27
sharding/README.md
Normal file
27
sharding/README.md
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
---
|
||||
layout: pattern
|
||||
title: Sharding
|
||||
folder: sharding
|
||||
permalink: /patterns/sharding/
|
||||
categories: Other
|
||||
tags:
|
||||
- Java
|
||||
- Difficulty-Beginner
|
||||
---
|
||||
|
||||
## Intent
|
||||
Sharding pattern means divide the data store into horizontal partitions or shards. Each shard has the same schema, but holds its own distinct subset of the data.
|
||||
A shard is a data store in its own right (it can contain the data for many entities of different types), running on a server acting as a storage node.
|
||||
|
||||
## Applicability
|
||||
This pattern offers the following benefits:
|
||||
|
||||
- You can scale the system out by adding further shards running on additional storage nodes.
|
||||
- A system can use off the shelf commodity hardware rather than specialized (and expensive) computers for each storage node.
|
||||
- You can reduce contention and improved performance by balancing the workload across shards.
|
||||
- In the cloud, shards can be located physically close to the users that will access the data.
|
||||
|
||||
## Credits
|
||||
|
||||
* [Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications - Sharding Pattern](https://docs.microsoft.com/en-us/previous-versions/msp-n-p/dn589797(v=pandp.10)?redirectedfrom=MSDN)
|
45
sharding/pom.xml
Normal file
45
sharding/pom.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
The MIT License
|
||||
Copyright © 2014-2019 Ilkka Seppälä
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<version>1.22.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>sharding</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
88
sharding/src/main/java/com/iluwatar/sharding/App.java
Normal file
88
sharding/src/main/java/com/iluwatar/sharding/App.java
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
/**
|
||||
* Sharding pattern means dividing a data store into a set of horizontal partitions
|
||||
* or shards. This pattern can improve scalability when storing and accessing large
|
||||
* volumes of data.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program main entry point.
|
||||
* @param args program runtime arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
var data1 = new Data(1, "data1", Data.DataType.type1);
|
||||
var data2 = new Data(2, "data2", Data.DataType.type2);
|
||||
var data3 = new Data(3, "data3", Data.DataType.type3);
|
||||
var data4 = new Data(4, "data4", Data.DataType.type1);
|
||||
|
||||
var shard1 = new Shard(1);
|
||||
var shard2 = new Shard(2);
|
||||
var shard3 = new Shard(3);
|
||||
|
||||
ShardManager manager = new LookupShardManager();
|
||||
manager.addNewShard(shard1);
|
||||
manager.addNewShard(shard2);
|
||||
manager.addNewShard(shard3);
|
||||
manager.storeData(data1);
|
||||
manager.storeData(data2);
|
||||
manager.storeData(data3);
|
||||
manager.storeData(data4);
|
||||
|
||||
shard1.clearData();
|
||||
shard2.clearData();
|
||||
shard3.clearData();
|
||||
|
||||
manager = new RangeShardManager();
|
||||
manager.addNewShard(shard1);
|
||||
manager.addNewShard(shard2);
|
||||
manager.addNewShard(shard3);
|
||||
manager.storeData(data1);
|
||||
manager.storeData(data2);
|
||||
manager.storeData(data3);
|
||||
manager.storeData(data4);
|
||||
|
||||
shard1.clearData();
|
||||
shard2.clearData();
|
||||
shard3.clearData();
|
||||
|
||||
manager = new HashShardManager();
|
||||
manager.addNewShard(shard1);
|
||||
manager.addNewShard(shard2);
|
||||
manager.addNewShard(shard3);
|
||||
manager.storeData(data1);
|
||||
manager.storeData(data2);
|
||||
manager.storeData(data3);
|
||||
manager.storeData(data4);
|
||||
|
||||
shard1.clearData();
|
||||
shard2.clearData();
|
||||
shard3.clearData();
|
||||
}
|
||||
|
||||
}
|
84
sharding/src/main/java/com/iluwatar/sharding/Data.java
Normal file
84
sharding/src/main/java/com/iluwatar/sharding/Data.java
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
/**
|
||||
* Basic data structure for each tuple stored in data shards.
|
||||
*/
|
||||
public class Data {
|
||||
|
||||
private int key;
|
||||
|
||||
private String value;
|
||||
|
||||
private DataType type;
|
||||
|
||||
/**
|
||||
* Constructor of Data class.
|
||||
* @param key data key
|
||||
* @param value data vlue
|
||||
* @param type data type
|
||||
*/
|
||||
public Data(final int key, final String value, final DataType type) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(final int key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public DataType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(DataType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
enum DataType {
|
||||
type1, type2, type3
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Data {" + "key="
|
||||
+ key + ", value='" + value
|
||||
+ '\'' + ", type=" + type + '}';
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* ShardManager with hash strategy. The purpose of this strategy is to reduce the
|
||||
* chance of hot-spots in the data. It aims to distribute the data across the shards
|
||||
* in a way that achieves a balance between the size of each shard and the average
|
||||
* load that each shard will encounter.
|
||||
*/
|
||||
public class HashShardManager extends ShardManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HashShardManager.class);
|
||||
|
||||
@Override
|
||||
public int storeData(Data data) {
|
||||
var shardId = allocateShard(data);
|
||||
var shard = shardMap.get(shardId);
|
||||
shard.storeData(data);
|
||||
LOGGER.info(data.toString() + " is stored in Shard " + shardId);
|
||||
return shardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int allocateShard(Data data) {
|
||||
var shardCount = shardMap.size();
|
||||
var hash = data.getKey() % shardCount;
|
||||
return hash == 0 ? hash + shardCount : hash;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* ShardManager with lookup strategy. In this strategy the sharding logic implements
|
||||
* a map that routes a request for data to the shard that contains that data by using
|
||||
* the shard key.
|
||||
*/
|
||||
public class LookupShardManager extends ShardManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LookupShardManager.class);
|
||||
|
||||
private Map<Integer, Integer> lookupMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public int storeData(Data data) {
|
||||
var shardId = allocateShard(data);
|
||||
lookupMap.put(data.getKey(), shardId);
|
||||
var shard = shardMap.get(shardId);
|
||||
shard.storeData(data);
|
||||
LOGGER.info(data.toString() + " is stored in Shard " + shardId);
|
||||
return shardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int allocateShard(Data data) {
|
||||
var key = data.getKey();
|
||||
if (lookupMap.containsKey(key)) {
|
||||
return lookupMap.get(key);
|
||||
} else {
|
||||
var shardCount = shardMap.size();
|
||||
var allocatedShardId = new Random().nextInt(shardCount - 1) + 1;
|
||||
return allocatedShardId;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* ShardManager with range strategy. This strategy groups related items together
|
||||
* in the same shard, and orders them by shard key.
|
||||
*/
|
||||
public class RangeShardManager extends ShardManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RangeShardManager.class);
|
||||
|
||||
@Override
|
||||
public int storeData(Data data) {
|
||||
var shardId = allocateShard(data);
|
||||
var shard = shardMap.get(shardId);
|
||||
shard.storeData(data);
|
||||
LOGGER.info(data.toString() + " is stored in Shard " + shardId);
|
||||
return shardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int allocateShard(Data data) {
|
||||
var type = data.getType();
|
||||
var shardId = -1;
|
||||
switch (type) {
|
||||
case type1:
|
||||
shardId = 1;
|
||||
break;
|
||||
case type2:
|
||||
shardId = 2;
|
||||
break;
|
||||
case type3:
|
||||
shardId = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return shardId;
|
||||
}
|
||||
|
||||
}
|
59
sharding/src/main/java/com/iluwatar/sharding/Shard.java
Normal file
59
sharding/src/main/java/com/iluwatar/sharding/Shard.java
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The Shard class stored data in a HashMap.
|
||||
*/
|
||||
public class Shard {
|
||||
|
||||
private final int id;
|
||||
|
||||
private Map<Integer, Data> dataStore;
|
||||
|
||||
public Shard(final int id) {
|
||||
this.id = id;
|
||||
this.dataStore = new HashMap<>();
|
||||
}
|
||||
|
||||
public void storeData(Data data) {
|
||||
dataStore.put(data.getKey(), data);
|
||||
}
|
||||
|
||||
public void clearData() {
|
||||
dataStore.clear();
|
||||
}
|
||||
|
||||
public Data getDataById(final int id) {
|
||||
return dataStore.get(id);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
103
sharding/src/main/java/com/iluwatar/sharding/ShardManager.java
Normal file
103
sharding/src/main/java/com/iluwatar/sharding/ShardManager.java
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Abstract class for ShardManager.
|
||||
*/
|
||||
public abstract class ShardManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ShardManager.class);
|
||||
|
||||
protected Map<Integer, Shard> shardMap;
|
||||
|
||||
public ShardManager() {
|
||||
shardMap = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a provided shard instance to shardMap.
|
||||
*
|
||||
* @param shard new shard instance.
|
||||
* @return {@code true} if succeed to add the new instance.
|
||||
* {@code false} if the shardId is already existed.
|
||||
*/
|
||||
public boolean addNewShard(final Shard shard) {
|
||||
var shardId = shard.getId();
|
||||
if (!shardMap.containsKey(shardId)) {
|
||||
shardMap.put(shardId, shard);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a shard instance by provided Id.
|
||||
*
|
||||
* @param shardId Id of shard instance to remove.
|
||||
* @return {@code true} if removed. {@code false} if the shardId is not existed.
|
||||
*/
|
||||
public boolean removeShardById(final int shardId) {
|
||||
if (shardMap.containsKey(shardId)) {
|
||||
shardMap.remove(shardId);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shard instance by provided shardId.
|
||||
*
|
||||
* @param shardId id of shard instance to get
|
||||
* @return required shard instance
|
||||
*/
|
||||
public Shard getShardById(final int shardId) {
|
||||
return shardMap.get(shardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store data in proper shard instance.
|
||||
*
|
||||
* @param data new data
|
||||
* @return id of shard that the data is stored in
|
||||
*/
|
||||
public abstract int storeData(final Data data);
|
||||
|
||||
/**
|
||||
* Allocate proper shard to provided data.
|
||||
*
|
||||
* @param data new data
|
||||
* @return id of shard that the data should be stored
|
||||
*/
|
||||
protected abstract int allocateShard(final Data data);
|
||||
|
||||
}
|
39
sharding/src/test/java/com/iluwatar/sharding/AppTest.java
Normal file
39
sharding/src/test/java/com/iluwatar/sharding/AppTest.java
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for App class.
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void testMain() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for HashShardManager class.
|
||||
*/
|
||||
public class HashShardManagerTest {
|
||||
|
||||
private HashShardManager hashShardManager;
|
||||
|
||||
/**
|
||||
* Initialize hashShardManager instance.
|
||||
*/
|
||||
@Before
|
||||
public void setup() {
|
||||
hashShardManager = new HashShardManager();
|
||||
var shard1 = new Shard(1);
|
||||
var shard2 = new Shard(2);
|
||||
var shard3 = new Shard(3);
|
||||
hashShardManager.addNewShard(shard1);
|
||||
hashShardManager.addNewShard(shard2);
|
||||
hashShardManager.addNewShard(shard3);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreData() {
|
||||
var data = new Data(1, "test", Data.DataType.type1);
|
||||
hashShardManager.storeData(data);
|
||||
Assert.assertEquals(data, hashShardManager.getShardById(1).getDataById(1));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for LookupShardManager class.
|
||||
*/
|
||||
public class LookupShardManagerTest {
|
||||
|
||||
private LookupShardManager lookupShardManager;
|
||||
|
||||
/**
|
||||
* Initialize lookupShardManager instance.
|
||||
*/
|
||||
@Before
|
||||
public void setup() {
|
||||
lookupShardManager = new LookupShardManager();
|
||||
var shard1 = new Shard(1);
|
||||
var shard2 = new Shard(2);
|
||||
var shard3 = new Shard(3);
|
||||
lookupShardManager.addNewShard(shard1);
|
||||
lookupShardManager.addNewShard(shard2);
|
||||
lookupShardManager.addNewShard(shard3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreData() {
|
||||
try {
|
||||
var data = new Data(1, "test", Data.DataType.type1);
|
||||
lookupShardManager.storeData(data);
|
||||
var field = LookupShardManager.class.getDeclaredField("lookupMap");
|
||||
field.setAccessible(true);
|
||||
Map<Integer, Integer> lookupMap = (Map<Integer, Integer>) field.get(lookupShardManager);
|
||||
var shardId = lookupMap.get(1);
|
||||
var shard = lookupShardManager.getShardById(shardId);
|
||||
Assert.assertEquals(data, shard.getDataById(1));
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
Assert.fail("Fail to modify field access.");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for RangeShardManager class.
|
||||
*/
|
||||
public class RangeShardManagerTest {
|
||||
|
||||
private RangeShardManager rangeShardManager;
|
||||
|
||||
/**
|
||||
* Initialize rangeShardManager instance.
|
||||
*/
|
||||
@Before
|
||||
public void setup() {
|
||||
rangeShardManager = new RangeShardManager();
|
||||
var shard1 = new Shard(1);
|
||||
var shard2 = new Shard(2);
|
||||
var shard3 = new Shard(3);
|
||||
rangeShardManager.addNewShard(shard1);
|
||||
rangeShardManager.addNewShard(shard2);
|
||||
rangeShardManager.addNewShard(shard3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreData() {
|
||||
var data = new Data(1, "test", Data.DataType.type1);
|
||||
rangeShardManager.storeData(data);
|
||||
Assert.assertEquals(data, rangeShardManager.getShardById(1).getDataById(1));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for ShardManager class.
|
||||
*/
|
||||
public class ShardManagerTest {
|
||||
|
||||
private ShardManager shardManager;
|
||||
|
||||
/**
|
||||
* Initialize shardManager instance.
|
||||
*/
|
||||
@Before
|
||||
public void setup() {
|
||||
shardManager = new TestShardManager();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddNewShard() {
|
||||
try {
|
||||
var shard = new Shard(1);
|
||||
shardManager.addNewShard(shard);
|
||||
var field = ShardManager.class.getDeclaredField("shardMap");
|
||||
field.setAccessible(true);
|
||||
Map<Integer, Shard> map = (Map<Integer, Shard>) field.get(shardManager);
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(shard, map.get(1));
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
Assert.fail("Fail to modify field access.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveShardById() {
|
||||
try {
|
||||
var shard = new Shard(1);
|
||||
shardManager.addNewShard(shard);
|
||||
boolean flag = shardManager.removeShardById(1);
|
||||
var field = ShardManager.class.getDeclaredField("shardMap");
|
||||
field.setAccessible(true);
|
||||
Map<Integer, Shard> map = (Map<Integer, Shard>) field.get(shardManager);
|
||||
Assert.assertEquals(true, flag);
|
||||
Assert.assertEquals(0, map.size());
|
||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||
Assert.fail("Fail to modify field access.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetShardById() {
|
||||
Shard shard = new Shard(1);
|
||||
shardManager.addNewShard(shard);
|
||||
Shard tmpShard = shardManager.getShardById(1);
|
||||
Assert.assertEquals(shard, tmpShard);
|
||||
}
|
||||
|
||||
class TestShardManager extends ShardManager {
|
||||
|
||||
@Override
|
||||
public int storeData(Data data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int allocateShard(Data data) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
83
sharding/src/test/java/com/iluwatar/sharding/ShardTest.java
Normal file
83
sharding/src/test/java/com/iluwatar/sharding/ShardTest.java
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2019 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for Shard class.
|
||||
*/
|
||||
public class ShardTest {
|
||||
|
||||
private Data data;
|
||||
|
||||
private Shard shard;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
data = new Data(1, "test", Data.DataType.type1);
|
||||
shard = new Shard(1);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {}
|
||||
|
||||
@Test
|
||||
public void testStoreData() {
|
||||
try {
|
||||
shard.storeData(data);
|
||||
var field = Shard.class.getDeclaredField("dataStore");
|
||||
field.setAccessible(true);
|
||||
Map<Integer, Data> dataMap = (Map<Integer, Data>) field.get(shard);
|
||||
Assert.assertEquals(1, dataMap.size());
|
||||
Assert.assertEquals(data, dataMap.get(1));
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
Assert.fail("Fail to modify field access.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearData() {
|
||||
try {
|
||||
Map<Integer, Data> dataMap = new HashMap<>();
|
||||
dataMap.put(1, data);
|
||||
var field = Shard.class.getDeclaredField("dataStore");
|
||||
field.setAccessible(true);
|
||||
field.set(shard, dataMap);
|
||||
shard.clearData();
|
||||
dataMap = (Map<Integer, Data>) field.get(shard);
|
||||
Assert.assertEquals(0, dataMap.size());
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
Assert.fail("Fail to modify field access.");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user