一致性hash算法相對傳統的按照機器數目取模的算法,最大的好處在於動態的進行機器的添加和摘除能夠不引發大面積的緩存失效。html
一致性hash的動態增長減小節點的緩存變化能夠參考博客:http://www.blogjava.net/hello-yun/archive/2012/10/10/389289.html
java
我要說的是針對redis的默認的分片按照加入的機器列表的順序來進行散列,這樣若是咱們動態的將中間的任意一個節點去掉,這個時候因爲每一個節點都是按照索引值做爲一個索引值做爲hash因素來進行位置計算的,這樣順序就會所有亂了。node
正確的作法是利用redis.clients.jedis.JedisShardInfo的 public JedisShardInfo(String host, int port, int timeout, String name) {
this(host, port, timeout, timeout, Sharded.DEFAULT_WEIGHT);
this.name = name;
}這個構造函數把name給傳遞過來,這個name每一個分片要都傳遞成惟一的,能夠是對應機器的ip和端口組成的字符串,這樣當咱們動態的減去獲取增長一個實例的時候,剩餘的機器在一致性hash環上面的位置保持不變,摘掉的機器會把請求散列到其餘的機器上面來,因爲虛擬節點的存在,咱們姑且認爲是徹底均勻的。redis
redis的最裏面的生成散列鍵的方法以下:算法
private void initialize(List<S> shards) {
nodes = new TreeMap<Long, S>();
for (int i = 0; i != shards.size(); ++i) {
final S shardInfo = shards.get(i);
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());
}
}緩存
黑色加粗的地方是咱們傳遞的name,紅色部分是若是不傳遞別名的話計算的key值,會影響在一致性hash環上面分片的位置,依賴外層的分片數量的循環,若是咱們傳遞name就不會存在摘掉節點或者增長節點大量緩存失效的問題了。
函數
我的的一點愚見,歡迎指教。
this