一致性hash算法--負載均衡


有沒有好奇過redis、memcache等是怎么實現集群負載均衡的呢?

其實他們都是通過一致性hash算法實現節點調度的。

講一致性hash算法前,先簡述一下求余hash算法:

hash(object)%N
  1. 一個緩存服務器宕機了,這樣所有映射到這台服務器的對象都會失效,我們需要把屬於該服務器中的緩存移除,這時候緩存服務器是 N-1 台,映射公式變成了 hash(object)%(N-1) ;
  2. 由於QPS升高,我們需要添加多一台服務器,這時候服務器是 N+1 台,映射公式變成了 hash(object)%(N+1) 。

1 和 2 的改變都會出現所有服務器需要進行數據遷移。

一致性HASH算法

一致性HASH算法的出現有效的解決了上面普通求余算法在節點變動后面臨全部緩存失效的問題:

  type Consistent struct {

  numOfVirtualNode int 

  hashSortedNodes []uint32

  circle map[uint32]string

  nodes map[string]bool

}

簡單地說,一致性哈希將整個哈希值空間組織成一個虛擬的圓環,如假設某空間哈希函數H的值空間是0-2^32-1(即哈希值是一個32位無符號整形),整個哈希空間如下:

下一步將各個服務器使用哈希算法計算出每台機器的位置,具體可以使用服務器的IP地址或者主機名作為關鍵字,並且是按照順時針排列:

  //這里我選擇crc32,具體情況具體安排

  func hashKey(host string) uint32 {

   scratch := []byte(host) 

  return crc32.ChecksumIEEE(scratch)

}

這里我們假設三台節點memcache經計算后位置如下:

  //add the node 

  c.Add("Memcache_server01") 

  c.Add("Memcache_server02") 

  c.Add("Memcache_server03")

  func (c *Consistent) Add(node string) error { 

  if _, ok := c.nodes[node]; ok { 

  return errors.New("host already existed") 

}

  c.nodes[node] = true 

  // add virtual node 

  for i := 0; i < c.numOfVirtualNode; i++ {

  virtualKey := getVirtualKey(i, node)

  c.circle[virtualKey] = node

  c.hashSortedNodes = append(c.hashSortedNodes, virtualKey)

 

  sort.Slice(c.hashSortedNodes, func(i, j int) bool {

  return c.hashSortedNodes[i] < c.hashSortedNodes[j]

  })

  return nil

}

接下來使用相同算法計算出數據的哈希值,並由此確定數據在此哈希環上的位置

假如我們有數據A、B、C和D,經過哈希計算后位置如下:

根據一致性哈希算法,數據A就被綁定到了server01上,D被綁定到了server02上,B、C在server03上,是按照順時針找最近服務節點方法

這樣得到的哈希環調度方法,有很高的容錯性和可擴展性:

假設server03宕機

可以看到此時A、C、B不會受到影響,只是將B、C節點被重定位到Server 1。一般的,在一致性哈希算法中,如果一台服務器不可用,則受影響的數據僅僅是此服務器到其環空間中前一台服務器(即順着逆時針方向行走遇到的第一台服務器)之間數據,其它不會受到影響。

考慮另外一種情況,如果我們在系統中增加一台服務器Memcached Server 04:

此時A、D、C不受影響,只有B需要重定位到新的Server 4。一般的,在一致性哈希算法中,如果增加一台服務器,則受影響的數據僅僅是新服務器到其環空間中前一台服務器(即順着逆時針方向行走遇到的第一台服務器)之間數據,其它不會受到影響。

有需要交流的小伙伴可以點擊這里加本人QQ:luke


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM