分佈式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

file
file

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章