一致性Hash(基於google Guava實現)
阿新 • • 發佈:2020-12-17
背景
一般我們使用的hash就是md5 sha 之類的工具類,在負載均衡會要求類似同一個ip在增加節點時還是定位到之前的節點,這時就要用到一致性hash。具體實現程式碼參考(基於google Guava):
使用谷歌 Guava 實現 Java 一致性雜湊 (用於根據雜湊Hash值平均分配的場景)一、介紹
MurmurHash演算法:高運算效能,低碰撞率,由Austin Appleby創建於2008年,現已應用到Hadoop、libstdc++、nginx、libmemcached等開源系統。2011年Appleby被Google僱傭,隨後Google推出其變種的CityHash演算法。
Java界中Redis,Memcached,Cassandra,HBase,Lucene都用它。
在Java的實現,Guava的Hashing類裡有,上面提到的Jedis,Cassandra裡都有Util類。
但存在的問題是由於Java的資料型別long與C語言中無符號長整型uint64_t有區別,導致Java輸出版本存在負數,針對這個問題進行了修改;另外需要注意的是中文不同編碼(UTF-8或GBK)會導致輸出結果的不同,使用中需要統一編碼。
p.s.一致性hash的實現演算法,murmurhash和ketamahash。下面這篇文章有詳細的說明。
淺析ketamahash和murmurhash - 程式詩人 - 部落格園二、原理
演算法圖例
三、效能測試對比
import java.nio.charset.StandardCharsets;
import org.apache.commons.codec.digest.DigestUtils;
import com.google.common.hash.Hashing;
public class Test {
public static void main(String[] args) {
System.out.println(murmur3Test("334324324234234sfsfsdfwwrtregreg"));
long startTime=System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
Test.md5Test("KFETHGRETWERFSDFWEFWEFWF");
}
long endTime=System.currentTimeMillis();
System.out.println("1000萬次md5Test演算法程式執行時間: " + (endTime - startTime ) + "ms");
long startTime2=System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
Test.murmur3Test("KFETHGRETWERFSDFWEFWEFWF");
}
long endTime2=System.currentTimeMillis();
System.out.println("1000萬次murmur3Test演算法程式執行時間: " + (endTime2 - startTime2 ) + "ms");
}
public static String murmur3Test(String primaryKey) {
return Hashing.murmur3_32().hashString(primaryKey, StandardCharsets.UTF_8).toString() +
"_" + primaryKey;
}
public static String md5Test(String primaryKey) {
return DigestUtils.md5Hex(primaryKey)+ "_" + primaryKey;
}
}
結論:
MurmurHash演算法比md5快一倍。
四、使用場景
1、根據uuid,通過hash演算法進行取模分庫分表
2、用來計算出key的slot值
3、短連結
五、其他演算法
ketamahash一致性雜湊演算法
由若干固定的虛擬節點來計算出每個虛擬節點的slots,資料儲存的時候,算出key的slot值,然後存入相鄰最近的虛擬節點
轉載hash函式MurmurHash_luoqinglong的專欄-CSDN部落格