Sharding Pattern (#1056)

* Create sharding module

* Add Unit Tests

* Fix readme hyperlink

* Fix check-style issue
This commit is contained in:
Azureyjt 2019-11-08 14:20:32 +08:00 committed by Ilkka Seppälä
parent 50986fa15b
commit 1fa8a604eb
16 changed files with 1010 additions and 0 deletions

View File

@ -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
View 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
View 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>

View 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();
}
}

View 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 + '}';
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View 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;
}
}

View 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);
}

View 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);
}
}

View File

@ -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));
}
}

View File

@ -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.");
}
}
}

View File

@ -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));
}
}

View File

@ -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;
}
}
}

View 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.");
}
}
}