應用於負載均衡的一致性雜湊及java實現

2021-09-01 06:57:27 字數 3618 閱讀 4547

這幾天看了幾遍一致性雜湊的文章,但是都沒有比較完整的實現,因此試著實現了一下,這裡我就不講一致性雜湊的原理了,網上很多,以一致性雜湊用在負載均衡的例項來說,一致性雜湊就是先把主機ip從小大到全部放到乙個環內,然後客戶端ip來連線的時候,把客戶端ip連線到大小最接近客戶端ip且大於客戶端ip的主機。當然,這裡的ip一般都是要先hash一下的。我的程式執行結果如下:

新增客戶端,一開始有4個主機,分別為s1,s2,s3,s4,每個主機有100個虛擬主機:

101客戶端(hash:-3872430075274208315)連線到主機->s2-192.168.1.2

102客戶端(hash:-6461488502093916753)連線到主機->s1-192.168.1.1

103客戶端(hash:-3272337528088901176)連線到主機->s3-192.168.1.3

104客戶端(hash:7274050343425899995)連線到主機->s2-192.168.1.2

105客戶端(hash:6218187750346216421)連線到主機->s1-192.168.1.1

106客戶端(hash:-8497989778066313989)連線到主機->s2-192.168.1.2

107客戶端(hash:2219601794372203979)連線到主機->s3-192.168.1.3

108客戶端(hash:1903054837754071260)連線到主機->s3-192.168.1.3

109客戶端(hash:-2425484502654523425)連線到主機->s1-192.168.1.1

刪除主機s2-192.168.1.2的變化:

hash(-8497989778066313989)改變到->s4-192.168.1.4

hash(7274050343425899995)改變到->s2-192.168.1.2

hash(-3872430075274208315)改變到->s4-192.168.1.4

hash(7274050343425899995)改變到->s1-192.168.1.1

增加主機s5-192.168.1.5的變化:

hash(1903054837754071260)改變到->s5-192.168.1.5

hash(1903054837754071260)改變到->s5-192.168.1.5

hash(-3272337528088901176)改變到->s5-192.168.1.5

最後的客戶端到主機的對映為:

hash(-8497989778066313989)連線到主機->s4-192.168.1.4

hash(-6461488502093916753)連線到主機->s1-192.168.1.1

hash(-3872430075274208315)連線到主機->s4-192.168.1.4

hash(-3272337528088901176)連線到主機->s5-192.168.1.5

hash(-2425484502654523425)連線到主機->s1-192.168.1.1

hash(1903054837754071260)連線到主機->s5-192.168.1.5

hash(2219601794372203979)連線到主機->s3-192.168.1.3

hash(6218187750346216421)連線到主機->s1-192.168.1.1

hash(7274050343425899995)連線到主機->s1-192.168.1.1

看結果可知:一開始新增到9個客戶端,連線到主機s1,s2,s3,s4的客戶端分別有3,3,3,0個,經過刪除主機s2,新增主機s5,最後9個客戶端分別連線到主機s1,s2,s3,s4,s5的個數為4,0,1,2,2.這裡要說明一下刪除主機s2的情況,hash尾號為9995的客戶端先連線到s2,再連線到s1,為什麼會出現這種情況呢?因為每乙個真實主機有n個虛擬主機,刪除s2卻列印「hash(7274050343425899995)改變到->s2-192.168.1.2」是因為刪除了s2的其中乙個虛擬主機,跳轉到另乙個虛擬主機,但還是在s2上,當然,這裡是列印中間情況,以便了解,真實的環境是刪除了s2後,所有他的虛擬節點都會馬上被刪除,虛擬節點上的連線也會重新連線到另乙個主機的虛擬節點,不會存在這種中間情況。

public class shard

public static void main(string args)

public static void printkeytree()

}private void init()

} //增加乙個主機

private void adds(node s)

//新增乙個虛擬節點進環形結構,lg為虛擬節點的hash值

public void adds(long lg,node s)else

nodes.put(lg, s);

for(iteratorit=between.keyset().iterator();it.hasnext();)else

} }//刪除真實節點是s

public void deletes(node s)

system.out.println("刪除主機"+s+"的變化:");

for(int i=0;itail = nodes.tailmap(hash("shard-" + s.name + "-node-" + i));

sortedmaphead = nodes.headmap(hash("shard-" + s.name + "-node-" + i));

long begin = 0l;

long end = 0l;

sortedmapbetween;

if(head.size()==0)else

for(iteratorit = between.keyset().iterator();it.hasnext();)else

}}

} //對映key到真實節點

public void keytonode(string key)

treekey.put(hash(key), tail.get(tail.firstkey()));

system.out.println(key+"(hash:"+hash(key)+")連線到主機->"+tail.get(tail.firstkey())); }

/*** murmurhash演算法,是非加密hash演算法,效能很高,

* 比傳統的crc32,md5,sha-1(這兩個演算法都是加密hash演算法,複雜度本身就很高,帶來的效能上的損害也不可避免)

* 等hash演算法要快很多,而且據說這個演算法的碰撞率很低.

* */

private static long hash(string key)

if (buf.remaining() > 0)

h ^= h >>> r;

h *= m;

h ^= h >>> r;

buf.order(byteorder);

return h; }

static class node

@override

public string tostring()

}}

參考:

應用負載均衡(輪詢 一致性雜湊)

今天看書看到了應用負載均衡的輪詢與一致性雜湊,其中說到,一致性雜湊可以根據應用請求的url或者url引數將系統的請求 到同一節點,而輪詢是將請求均勻地 到每個伺服器。1 輪詢 1 2 3 優點 到後端應用的請求更加均勻,使得每個伺服器基本均衡 缺點 隨著後端應用伺服器的增加,快取的命中率為下降,這種...

負載均衡與一致性雜湊

一 負載均衡 1.應用場景 假設有三颱快取伺服器s0,s1,s2,同時有三萬張需要快取,最好可以均勻的快取到伺服器上,這樣可以分擔快取的壓力。2.解決方法 對快取下的鍵進行hash計算,雜湊後的值是個整數,再用快取伺服器的數量對這個值進行取模計算,餘數決定資料應該快取到哪台伺服器上。hash 名稱 ...

Nginx負載均衡之一致性雜湊演算法

nginx提供了多種負載均衡演算法,ip hash是其中的一種,但是通常情況下不用他而用第三方的演算法,為什麼?因為ip hash在nginx是第一層 時才有效果,如果在經過nginx前經過了其他 時,會造成獲取的ip不正確。upstream web server常用的一致性雜湊演算法 ngx ht...