@@ -26,20 +26,69 @@ import (
2626
2727type Hash func (data []byte ) uint32
2828
29+ const defaultHashExpansion = 6
30+
2931type Map struct {
32+ // Inputs
33+
34+ // hash is the hash function that will be applied to both added
35+ // keys and fetched keys
3036 hash Hash
37+
38+ // replicas is the number of virtual nodes that will be inserted
39+ // into the consistent hash ring for each key added
3140 replicas int
41+
42+ // prefixTableExpansion is the multiple of virtual nodes that
43+ // will be inserted into the internal hash table for O(1) lookups.
3244 prefixTableExpansion int
3345
46+
47+
48+ // Internal data
49+
50+ // keys is the hash of the virtual nodes, sorted by hash value
3451 keys []int // Sorted
52+
53+ // hashMap maps the hashed keys back to the input strings.
54+ // Note that all virtual nodes will map back to the same input
55+ // string
3556 hashMap map [int ]string
3657
37- prefixBits uint32
58+ // prefixShift is the number of bits an input hash should
59+ // be right-shifted to act as a lookup in the prefixTable
3860 prefixShift uint32
61+
62+ // prefixTable is a map of the most significant bits of
63+ // a hash value to output all hashes with that prefix
64+ // map to. If the result is ambiguous (i.e. there is a
65+ // hash range split within this prefix) the value will
66+ // be blank and we should fall back to a binary search
67+ // through keys to find the exact output
3968 prefixTable []string
4069}
4170
42- func New (replicas int , tableExpansion int , fn Hash ) * Map {
71+ // New returns a blank consistent hash ring that will return
72+ // the key whos hash comes next after the hash of the input to
73+ // Get().
74+ // Increasing the number of replicas will improve the smoothness
75+ // of the hash ring and reduce the data moved when adding/removing
76+ // nodes, at the cost of more memory.
77+ func New (replicas int , fn Hash ) * Map {
78+ return NewConsistentHash (replicas , defaultHashExpansion , fn )
79+ }
80+
81+
82+ // NewConsistentHash returns a blank consistent hash ring that will return
83+ // the key whos hash comes next after the hash of the input to
84+ // Get().
85+ // Increasing the number of replicas will improve the smoothness
86+ // of the hash ring and reduce the data moved when adding/removing
87+ // nodes.
88+ // Increasing the tableExpansion will allocate more entries in the
89+ // internal hash table, reducing the frequency of lg(n) binary
90+ // searches during Get() calls.
91+ func NewConsistentHash (replicas int , tableExpansion int , fn Hash ) * Map {
4392 m := & Map {
4493 replicas : replicas ,
4594 hash : fn ,
@@ -69,10 +118,10 @@ func (m *Map) Add(keys ...string) {
69118 sort .Ints (m .keys )
70119
71120 // Find minimum number of bits to hold |keys| * prefixTableExpansion
72- m . prefixBits = uint32 (bits .Len32 (uint32 (len (m .keys ) * m .prefixTableExpansion )))
73- m .prefixShift = 32 - m . prefixBits
121+ prefixBits : = uint32 (bits .Len32 (uint32 (len (m .keys ) * m .prefixTableExpansion )))
122+ m .prefixShift = 32 - prefixBits
74123
75- prefixTableSize := 1 << m . prefixBits
124+ prefixTableSize := 1 << prefixBits
76125 m .prefixTable = make ([]string , prefixTableSize )
77126
78127 previousKeyPrefix := - 1 // Effectively -Inf
0 commit comments