github.com/searKing/golang/go@v1.2.117/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 // 84 // comparisons</a> 85 // 86 // @see <a href="http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash">fnv at 87 // 88 // wikipedia</a> 89 func fnv164Hash(k string) []uint32 { 90 hash := fnv.New64() 91 hash.Write([]byte(k)) 92 rv := hash.Sum64() 93 return []uint32{uint32(rv & 0xffffffff)} // Truncate to 32-bits 94 } 95 96 // Variation of FNV. 97 func fnv1a64Hash(k string) []uint32 { 98 hash := fnv.New64a() 99 hash.Write([]byte(k)) 100 rv := (hash.Sum64() >> 16) & 0x7fff 101 return []uint32{uint32(rv & 0xffffffff)} // Truncate to 32-bits 102 } 103 104 // 32-bit FNV1. 105 func fnv132Hash(k string) []uint32 { 106 hash := fnv.New32() 107 hash.Write([]byte(k)) 108 rv := (hash.Sum32() >> 16) & 0x7fff 109 return []uint32{rv & 0xffffffff} // Truncate to 32-bits 110 } 111 112 // 32-bit FNV1a. 113 func fnv1a32Hash(k string) []uint32 { 114 hash := fnv.New32a() 115 hash.Write([]byte(k)) 116 rv := (hash.Sum32() >> 16) & 0x7fff 117 return []uint32{rv & 0xffffffff} // Truncate to 32-bits 118 } 119 120 // 128-bit FNV1. 121 func fnv1128Hash(k string) []uint32 { 122 hash := fnv.New128() 123 hash.Write([]byte(k)) 124 bKey := hash.Sum(nil) 125 rv := binary.LittleEndian.Uint32(bKey) 126 return []uint32{rv & 0xffffffff} // Truncate to 32-bits 127 } 128 129 // 128-bit FNV1a. 130 func fnv1a128Hash(k string) []uint32 { 131 hash := fnv.New128a() 132 hash.Write([]byte(k)) 133 bKey := hash.Sum(nil) 134 rv := binary.LittleEndian.Uint32(bKey) 135 return []uint32{uint32(rv & 0xffffffff)} // Truncate to 32-bits 136 } 137 138 // MD5-based hash algorithm used by ketama. 139 func ketamaHash(k string) []uint32 { 140 h := md5.New() 141 h.Write([]byte(k)) 142 digest := h.Sum(nil) 143 var rvs []uint32 144 // 16B -> [4B, 4B, 4B, 4B] 145 for h := 0; h < 4; h++ { 146 k := binary.LittleEndian.Uint32(digest[h*4:]) 147 rvs = append(rvs, k) 148 } 149 return rvs 150 }