github.com/searKing/golang/go@v1.2.74/container/hashring/hash_algorithm.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package hashring 6 7 import ( 8 "crypto/md5" 9 "encoding/binary" 10 "hash/crc32" 11 "hash/fnv" 12 ) 13 14 // Intents to provide hash for locating a server for a key. 15 type HashAlgorithm interface { 16 // Compute the hash for the given key. 17 // @return a positive integer hash 18 Hash(k string) []uint32 19 } 20 21 type HashFunc func(k string) []uint32 22 23 func (f HashFunc) Hash(k string) []uint32 { 24 return f(k) 25 } 26 27 // Known hashing algorithms for locating a server for a key. Note that all hash 28 // algorithms return 64-bits of hash, but only the lower 32-bits are 29 // significant. This allows a positive 32-bit number to be returned for all 30 // cases. 31 var ( 32 // CRCHash hash algorithm by crc32. 33 CRCHash = HashFunc(crcHash) 34 // CRCPerlHash as used by the perl API. This will be more consistent both 35 // across multiple API users as well as java versions, but is mostly likely 36 // significantly slower. 37 CRCPerlHash = HashFunc(crcPerlHash) 38 // FNV hashes are designed to be fast while maintaining a low collision rate. 39 // The FNV speed allows one to quickly hash lots of data while maintaining a 40 // reasonable collision rate. 41 // 42 // @see <a href="http://www.isthe.com/chongo/tech/comp/fnv/">fnv 43 // comparisons</a> 44 // @see <a href="http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash">fnv at 45 // wikipedia</a> 46 // 32-bit FNV1. 47 FNV132Hash = HashFunc(fnv132Hash) 48 // Variation of FNV. 49 // 32-bit FNV1a. 50 FNV1a32Hash = HashFunc(fnv1a32Hash) 51 // 64-bit FNV1. 52 FNV164Hash = HashFunc(fnv164Hash) 53 // 64-bit FNV1a. 54 FNV1a64Hash = HashFunc(fnv1a64Hash) 55 // 128-bit FNV1. 56 FNV1128Hash = HashFunc(fnv1128Hash) 57 // 128-bit FNV1a. 58 FNV1a128Hash = HashFunc(fnv1a128Hash) 59 // MD5-based hash algorithm used by ketama. 60 KetamaHash = HashFunc(ketamaHash) 61 ) 62 63 func crcHash(k string) []uint32 { 64 rv := crc32.ChecksumIEEE([]byte(k)) 65 return []uint32{rv} 66 } 67 68 func crcPerlHash(k string) []uint32 { 69 // return (crc32(shift) >> 16) & 0x7fff; 70 71 //crc32 := crc32.NewIEEE() 72 //crc32.Write([]byte(k)) 73 //rv := (crc32.Sum32() >> 16) & 0x7fff 74 rv := crc32.ChecksumIEEE([]byte(k)) 75 return []uint32{(rv >> 16) & 0x7fff} // Truncate to 16-bits 76 } 77 78 // FNV hashes are designed to be fast while maintaining a low collision rate. 79 // The FNV speed allows one to quickly hash lots of data while maintaining a 80 // reasonable collision rate. 81 // 82 // @see <a href="http://www.isthe.com/chongo/tech/comp/fnv/">fnv 83 // comparisons</a> 84 // @see <a href="http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash">fnv at 85 // wikipedia</a> 86 func fnv164Hash(k string) []uint32 { 87 hash := fnv.New64() 88 hash.Write([]byte(k)) 89 rv := hash.Sum64() 90 return []uint32{uint32(rv & 0xffffffff)} // Truncate to 32-bits 91 } 92 93 // Variation of FNV. 94 func fnv1a64Hash(k string) []uint32 { 95 hash := fnv.New64a() 96 hash.Write([]byte(k)) 97 rv := (hash.Sum64() >> 16) & 0x7fff 98 return []uint32{uint32(rv & 0xffffffff)} // Truncate to 32-bits 99 } 100 101 // 32-bit FNV1. 102 func fnv132Hash(k string) []uint32 { 103 hash := fnv.New32() 104 hash.Write([]byte(k)) 105 rv := (hash.Sum32() >> 16) & 0x7fff 106 return []uint32{rv & 0xffffffff} // Truncate to 32-bits 107 } 108 109 // 32-bit FNV1a. 110 func fnv1a32Hash(k string) []uint32 { 111 hash := fnv.New32a() 112 hash.Write([]byte(k)) 113 rv := (hash.Sum32() >> 16) & 0x7fff 114 return []uint32{rv & 0xffffffff} // Truncate to 32-bits 115 } 116 117 // 128-bit FNV1. 118 func fnv1128Hash(k string) []uint32 { 119 hash := fnv.New128() 120 hash.Write([]byte(k)) 121 bKey := hash.Sum(nil) 122 rv := binary.LittleEndian.Uint32(bKey) 123 return []uint32{rv & 0xffffffff} // Truncate to 32-bits 124 } 125 126 // 128-bit FNV1a. 127 func fnv1a128Hash(k string) []uint32 { 128 hash := fnv.New128a() 129 hash.Write([]byte(k)) 130 bKey := hash.Sum(nil) 131 rv := binary.LittleEndian.Uint32(bKey) 132 return []uint32{uint32(rv & 0xffffffff)} // Truncate to 32-bits 133 } 134 135 // MD5-based hash algorithm used by ketama. 136 func ketamaHash(k string) []uint32 { 137 h := md5.New() 138 h.Write([]byte(k)) 139 digest := h.Sum(nil) 140 var rvs []uint32 141 // 16B -> [4B, 4B, 4B, 4B] 142 for h := 0; h < 4; h++ { 143 k := binary.LittleEndian.Uint32(digest[h*4:]) 144 rvs = append(rvs, k) 145 } 146 return rvs 147 }