https://www.cnblogs.com/ldaniel/p/5413821.html
一致性哈希的具体介绍,可以参考:http://www.cnblogs.com/haippy/archive/2011/12/10/2282943.html
1 import ( 2 "hash/crc32" 3 "sort" 4 "strconv" 5 "sync" 6 ) 7 8 const DEFAULT_REPLICAS = 100 9 type SortKeys []uint32 10 11 func (sk SortKeys) Len() int { 12 return len(sk) 13 } 14 15 func (sk SortKeys) Less(i, j int) bool { 16 return sk[i] < sk[j] 17 } 18 19 func (sk SortKeys) Swap(i, j int) { 20 sk[i], sk[j] = sk[j], sk[i] 21 } 22 23 type HashRing struct { 24 Nodes map[uint32]string 25 Keys SortKeys 26 sync.RWMutex 27 } 28 29 func (hr *HashRing)New(nodes []string) { 30 if nodes == nil { 31 return 32 } 33 34 hr.Nodes = make(map[uint32]string) 35 hr.Keys = SortKeys{} 36 for _, node := range(nodes) { 37 for i := 0; i < DEFAULT_REPLICAS; i++ { 38 str := node + strconv.Itoa(i) 39 hr.Nodes[hr.hashStr(str)] = node 40 hr.Keys = append(hr.Keys, hr.hashStr(str)) 41 } 42 } 43 sort.Sort(hr.Keys) 44 } 45 46 func (hr *HashRing) hashStr(key string) uint32 { 47 return crc32.ChecksumIEEE([]byte(key)) 48 } 49 50 func (hr *HashRing) GetNode(key string) string { 51 hr.RLock() 52 defer hr.RUnlock() 53 hash := hr.hashStr(key) 54 i := hr.get_position(hash) 55 return hr.Nodes[hr.Keys[i]] 56 } 57 58 func (hr *HashRing) get_position(hash uint32) int { 59 i := sort.Search(len(hr.Keys), func(i int) bool { 60 return hr.Keys[i] >= hash}) 61 62 if i < len(hr.Keys) { 63 if i == len(hr.Keys) - 1 { 64 return 0 65 } else { 66 return i 67 } 68 } else { 69 return len(hr.Keys) - 1 70 } 71 } 72 73
基本思想:
(1)一共有16384个槽,每台服务器分管其中的一部分
(2)插入一个数据的时候,先根据CRC16算法计算key对应的值,然后用该值对16384取余数(即CRC16(key) mod 16384),确定将数据放到哪个槽里面
(3)在增加的时候,之前的节点各自分出一些槽给新节点,对应的数据也一起迁出
(4)客户端可以向任何一个Redis节点发送请求,然后由节点将请求重定向到正确的节点上
为什么要选择的槽是16384个呢?
crc16会输出16bit的结果,可以看作是一个分布在0-2^16-1之间的数,redis的作者测试发现这个数对2^{14}求模的会将key在0-2^{14-1}之间分布得很均匀,因此选了这个值。
参考资料:
[1]https://www.cnblogs.com/abc-begin/p/8203613.html
[2]哈希算法:https://blog.csdn.net/tanggao1314/article/details/51457585
作者:尚亦汐
链接:https://www.jianshu.com/p/fa623e59fdcf
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。