jedis中sharejedis一致性hash實現(xiàn)
- Redis服務(wù)器節(jié)點劃分:將每臺服務(wù)器節(jié)點采用hash算法劃分為160個虛擬節(jié)點(可以配置劃分權(quán)重)
- 將劃分虛擬節(jié)點采用TreeMap存儲
- 對每個Redis服務(wù)器的物理連接采用LinkedHashMap存儲
- 對Key or KeyTag 采用同樣的hash算法,然后從TreeMap獲取大于等于鍵hash值得節(jié)點,取最鄰近節(jié)點存儲;當(dāng)* * key的hash值大于虛擬節(jié)點hash值得最大值時,存入第一個虛擬節(jié)點
- sharded采用的hash算法:MD5 和 MurmurHash兩種;默認(rèn)采用64位的MurmurHash算法;有興趣的可以 研究下,MurmurHash是一種高效,低碰撞的hash算法;參考地址:
http://blog.csdn.net/yfkiss/article/details/7337382
https://sites.google.com/site/murmurhash/
public static final int DEFAULT_WEIGHT = 1;
private TreeMap<Long, S> nodes;
private final Hashing algo;// hash算法
//shardinfo對應(yīng)的jedis連接
private final Map<ShardInfo<R>, R> resources = new LinkedHashMap<ShardInfo<R>, R>();
//shards 所有的服務(wù)器節(jié)點列表
private void initialize(List<S> shards) {
// TreeMap的hash環(huán)
nodes = new TreeMap<Long, S>();
// 遍歷節(jié)點
for (int i = 0; i != shards.size(); ++i) {
final S shardInfo = shards.get(i);
//每個節(jié)點創(chuàng)建160個虛擬節(jié)點
if (shardInfo.getName() == null)
for (int n = 0; n < 160 * shardInfo.getWeight(); n++){
nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n), shardInfo);
}
else for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {
nodes.put(this.algo.hash(shardInfo.getName() + "*" + shardInfo.getWeight() + n), shardInfo);
}
resources.put(shardInfo, shardInfo.createResource());
}
}
// 獲取一個節(jié)點
public S getShardInfo(byte[] key) {
//返回大于key的部分子map
SortedMap<Long, S> tail = nodes.tailMap(algo.hash(key));
if (tail.isEmpty()) {
return nodes.get(nodes.firstKey());
}
//返回map中key值最小的一個
return tail.get(tail.firstKey());
}
// 獲得一個jedis
public R getShard(String key) {
return resources.get(getShardInfo(key));
}
public S getShardInfo(String key) {
return getShardInfo(SafeEncoder.encode(getKeyTag(key)));
}