1. 程式人生 > 其它 >分散式hash相關內容

分散式hash相關內容

Hash演算法相關內容

⾸先有⼀條直線,直線開頭和結尾分別定為為1和2的32次⽅減1,這相當於⼀個地址,對於這樣⼀條
線,彎過來構成⼀個圓環形成閉環,這樣的⼀個圓環稱為hash環。我們把伺服器的ip或者主機名求
hash值然後對應到hash環上,那麼針對客戶端⽤戶,也根據它的ip進⾏hash求值,對應到環上某個位
置,然後如何確定⼀個客戶端路由到哪個伺服器處理呢?按照順時針⽅向找最近的伺服器節點
假如將伺服器3下線,伺服器3下線後,原來路由到3的客戶端重新路由到伺服器4,對於其他客戶端沒有
影響只是這⼀⼩部分受影響(請求的遷移達到了最⼩,這樣的演算法對分散式叢集來說⾮常合適的,避免
了⼤量請求遷移 )
增加伺服器5之後,原來路由到3的部分客戶端路由到新增伺服器5上,對於其他客戶端沒有影響只是這
⼀⼩部分受影響(請求的遷移達到了最⼩,這樣的演算法對分散式叢集來說⾮常合適的,避免了⼤量請求
遷移 )
1)如前所述,每⼀臺伺服器負責⼀段,⼀致性雜湊演算法對於節點的增減都只需重定位環空間中的⼀⼩
部分資料,具有較好的容錯性和可擴充套件性。
但是,⼀致性雜湊演算法在服務節點太少時,容易因為節點分部不均勻⽽造成資料傾斜問題。例如系統中
只有兩臺伺服器,其環分佈如下,節點2只能負責⾮常⼩的⼀段,⼤量的客戶端
請求落在了節點1上,這就是資料(請求)傾斜問題
2)為了解決這種資料傾斜問題,⼀致性雜湊演算法引⼊了虛擬節點機制,即對每⼀個服務節點計算多個
雜湊,每個計算結果位置都放置⼀個此服務節點,稱為虛擬節點。
具體做法可以在伺服器ip或主機名的後⾯增加編號來實現。⽐如,可以為每臺伺服器計算三個虛擬節
點,於是可以分別計算 “節點1的ip#1”、“節點1的ip#2”、“節點1的ip#3”、“節點2的ip#1”、“節點2的
ip#2”、“節點2的ip#3”的雜湊值,於是形成六個虛擬節點,當客戶端被路由到虛擬節點的時候其實是被
路由到該虛擬節點所對應的真實節點

一致性Hash演算法的程式碼

普通hash演算法

/**
* 普通Hash演算法實現
*/
public class GeneralHash {
public static void main(String[] args) {
// 定義客戶端IP
String[] clients = new String[]
{"10.78.12.3","113.25.63.1","126.12.3.8"};
// 定義伺服器數量
int serverCount = 5;// (編號對應0,1,2)
// hash(ip)%node_counts=index
//根據index鎖定應該路由到的tomcat伺服器
for(String client: clients) {
int hash = Math.abs(client.hashCode());
int index = hash%serverCount;
System.out.println("客戶端:" + client + " 被路由到伺服器編號為:" + index);
 }
 }
}

一致性hash演算法不帶虛擬節點

public class ConsistentHashNoVirtual {
public static void main(String[] args) {
//step1 初始化:把伺服器節點IP的雜湊值對應到雜湊環上
// 定義伺服器ip
String[] tomcatServers = new String[]
{"123.111.0.0","123.101.3.1","111.20.35.2","123.98.26.3"};
SortedMap<Integer,String> hashServerMap = new TreeMap<>();
for(String tomcatServer: tomcatServers) {
// 求出每⼀個ip的hash值,對應到hash環上,儲存hash值與ip的對應關係
int serverHash = Math.abs(tomcatServer.hashCode());
// 儲存hash值與ip的對應關係
hashServerMap.put(serverHash,tomcatServer);
 }
//step2 針對客戶端IP求出hash值
// 定義客戶端IP
String[] clients = new String[]
{"10.78.12.3","113.25.63.1","126.12.3.8"};
for(String client : clients) {
int clientHash = Math.abs(client.hashCode());
//step3 針對客戶端,找到能夠處理當前客戶端請求的伺服器(雜湊環上順時針最
近)
// 根據客戶端ip的雜湊值去找出哪⼀個伺服器節點能夠處理()
SortedMap<Integer, String> integerStringSortedMap =
hashServerMap.tailMap(clientHash);
if(integerStringSortedMap.isEmpty()) {
// 取雜湊環上的順時針第⼀臺伺服器
Integer firstKey = hashServerMap.firstKey();
System.out.println("==========>>>>客戶端:" + client + " 被
路由到伺服器:" + hashServerMap.get(firstKey));
 }else{
Integer firstKey = integerStringSortedMap.firstKey();
System.out.println("==========>>>>客戶端:" + client + " 被
路由到伺服器:" + hashServerMap.get(firstKey));
 }
 }
 }
}

一致性hash演算法帶虛擬節點

public class ConsistentHashWithVirtual {
public static void main(String[] args) {
//step1 初始化:把伺服器節點IP的雜湊值對應到雜湊環上
// 定義伺服器ip
String[] tomcatServers = new String[]
{"123.111.0.0","123.101.3.1","111.20.35.2","123.98.26.3"};
SortedMap<Integer,String> hashServerMap = new TreeMap<>();
// 定義針對每個真實伺服器虛擬出來⼏個節點
int virtaulCount = 3;
for(String tomcatServer: tomcatServers) {
// 求出每⼀個ip的hash值,對應到hash環上,儲存hash值與ip的對應關係
int serverHash = Math.abs(tomcatServer.hashCode());
// 儲存hash值與ip的對應關係
hashServerMap.put(serverHash,tomcatServer);
// 處理虛擬節點
for(int i = 0; i < virtaulCount; i++) {
int virtualHash = Math.abs((tomcatServer + "#" + i).hashCode());
hashServerMap.put(virtualHash,"----由虛擬節點"+ i + "對映過
來的請求:"+ tomcatServer);
 }
 }
//step2 針對客戶端IP求出hash值
// 定義客戶端IP
String[] clients = new String[]
{"10.78.12.3","113.25.63.1","126.12.3.8"};
for(String client : clients) {
int clientHash = Math.abs(client.hashCode());
//step3 針對客戶端,找到能夠處理當前客戶端請求的伺服器(雜湊環上順時針最
近)
// 根據客戶端ip的雜湊值去找出哪⼀個伺服器節點能夠處理()
SortedMap<Integer, String> integerStringSortedMap =
hashServerMap.tailMap(clientHash);
if(integerStringSortedMap.isEmpty()) {
// 取雜湊環上的順時針第⼀臺伺服器
Integer firstKey = hashServerMap.firstKey();
System.out.println("==========>>>>客戶端:" + client + " 被
路由到伺服器:" + hashServerMap.get(firstKey));
 }else{
Integer firstKey = integerStringSortedMap.firstKey();
System.out.println("==========>>>>客戶端:" + client + " 被
路由到伺服器:" + hashServerMap.get(firstKey));
 }
 }
 }
}

歡迎搜尋關注本人與朋友共同開發的微信面經小程式【大廠面試助手】和公眾號【微瞰技術】,以及總結的分類面試題https://github.com/zhendiao/JavaInterview