Added sharding benchmark and removed some imports

This commit is contained in:
Jonathan Leibiusky
2010-09-30 21:04:21 -03:00
parent 39618506e4
commit 6a1e141064
10 changed files with 2997 additions and 2945 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
package redis.clients.jedis;
import redis.clients.util.FixedResourcePool;
import redis.clients.util.ShardInfo;
public class JedisPool extends FixedResourcePool<Jedis> {
private String host;

View File

@@ -8,10 +8,9 @@ import java.util.regex.Pattern;
import redis.clients.jedis.Client.LIST_POSITION;
import redis.clients.util.Hashing;
import redis.clients.util.ShardInfo;
import redis.clients.util.Sharded;
public class ShardedJedis extends Sharded<Jedis,JedisShardInfo> {
public class ShardedJedis extends Sharded<Jedis, JedisShardInfo> {
public ShardedJedis(List<JedisShardInfo> shards) {
super(shards);
}
@@ -21,13 +20,14 @@ public class ShardedJedis extends Sharded<Jedis,JedisShardInfo> {
}
public ShardedJedis(List<JedisShardInfo> shards, Pattern keyTagPattern) {
super(shards, keyTagPattern);
super(shards, keyTagPattern);
}
public ShardedJedis(List<JedisShardInfo> shards, Hashing algo, Pattern keyTagPattern) {
super(shards, algo, keyTagPattern);
public ShardedJedis(List<JedisShardInfo> shards, Hashing algo,
Pattern keyTagPattern) {
super(shards, algo, keyTagPattern);
}
public String set(String key, String value) {
Jedis j = getShard(key);
return j.set(key, value);

View File

@@ -8,85 +8,95 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Sharded<R, S extends ShardInfo<R>> {
public static final int DEFAULT_WEIGHT = 1;
public static final int DEFAULT_WEIGHT = 1;
private TreeMap<Long, S> nodes;
private final Hashing algo;
/**
* The default pattern used for extracting a key tag.
* The pattern must have a group (between parenthesis), which delimits the tag to be hashed.
* A null pattern avoids applying the regular expression for each lookup, improving performance a little bit
* is key tags aren't being used.
/**
* The default pattern used for extracting a key tag. The pattern must have
* a group (between parenthesis), which delimits the tag to be hashed. A
* null pattern avoids applying the regular expression for each lookup,
* improving performance a little bit is key tags aren't being used.
*/
private Pattern tagPattern = null;
public static final Pattern DEFAULT_KEY_TAG_PATTERN = Pattern.compile("\\{(.+?)\\}"); // the tag is anything between {}
private Pattern tagPattern = null;
// the tag is anything between {}
public static final Pattern DEFAULT_KEY_TAG_PATTERN = Pattern
.compile("\\{(.+?)\\}");
public Sharded(List<S> shards) {
this(shards, Hashing.MURMUR_HASH); // MD5 is really not good as we works with 64-bits not 128
this(shards, Hashing.MURMUR_HASH); // MD5 is really not good as we works
// with 64-bits not 128
}
public Sharded(List<S> shards, Hashing algo) {
this.algo = algo;
initialize(shards);
this.algo = algo;
initialize(shards);
}
public Sharded(List<S> shards, Pattern tagPattern) {
this(shards, Hashing.MURMUR_HASH, tagPattern); // MD5 is really not good as we works with 64-bits not 128
this(shards, Hashing.MURMUR_HASH, tagPattern); // MD5 is really not good
// as we works with
// 64-bits not 128
}
public Sharded(List<S> shards, Hashing algo, Pattern tagPattern) {
this.algo = algo;
this.tagPattern = tagPattern;
initialize(shards);
this.algo = algo;
this.tagPattern = tagPattern;
initialize(shards);
}
private void initialize(List<S> shards) {
nodes = new TreeMap<Long, S>();
nodes = new TreeMap<Long, S>();
int totalWeight = 0;
int totalWeight = 0;
for (ShardInfo shard : shards) {
totalWeight += shard.getWeight();
}
for (ShardInfo<?> shard : shards) {
totalWeight += shard.getWeight();
}
long oneForthOfStep = (1L << 62) / totalWeight; // 62 vs 64 to normalize math in Long
long oneForthOfStep = (1L << 62) / totalWeight; // 62 vs 64 to normalize
// math in Long
long floor = Long.MIN_VALUE;
for (int i = 0; i != shards.size(); ++i) {
final S shardInfo = shards.get(i);
shardInfo.initResource();
nodes.put(floor, shardInfo);
floor += 4 * oneForthOfStep * shardInfo.getWeight(); // *4 to compensate 62 vs 64
}
long floor = Long.MIN_VALUE;
for (int i = 0; i != shards.size(); ++i) {
final S shardInfo = shards.get(i);
shardInfo.initResource();
nodes.put(floor, shardInfo);
floor += 4 * oneForthOfStep * shardInfo.getWeight(); // *4 to
// compensate
// 62 vs 64
}
}
public R getShard(String key) {
return nodes.floorEntry(algo.hash(getKeyTag(key))).getValue().getResource();
return nodes.floorEntry(algo.hash(getKeyTag(key))).getValue()
.getResource();
}
public S getShardInfo(String key) {
return nodes.floorEntry(algo.hash(getKeyTag(key))).getValue();
return nodes.floorEntry(algo.hash(getKeyTag(key))).getValue();
}
/**
* A key tag is a special pattern inside a key that, if preset, is the only part of the key hashed
* in order to select the server for this key.
* A key tag is a special pattern inside a key that, if preset, is the only
* part of the key hashed in order to select the server for this key.
*
* @see http://code.google.com/p/redis/wiki/FAQ#I'm_using_some_form_of_key_hashing_for_partitioning,_but_wh
* @see http://code.google.com/p/redis/wiki/FAQ#I
* 'm_using_some_form_of_key_hashing_for_partitioning,_but_wh
* @param key
* @return The tag if it exists, or the original key
* @return The tag if it exists, or the original key
*/
public String getKeyTag(String key){
if (tagPattern != null){
Matcher m = tagPattern.matcher(key);
if (m.find())
return m.group(1);
}
return key;
public String getKeyTag(String key) {
if (tagPattern != null) {
Matcher m = tagPattern.matcher(key);
if (m.find())
return m.group(1);
}
return key;
}
public Collection<S> getAllShards() {
return Collections.unmodifiableCollection(nodes.values());
return Collections.unmodifiableCollection(nodes.values());
}
}