What is consistent hashing and when would you use it in a Go distributed system?
go-sys-002
Your answer
Answer as you would in a real interview — explain your thinking, not just the conclusion.
Model answer
Consistent hashing maps both keys and nodes onto a ring of hash values (0 to 2^32). A key is assigned to the first node clockwise from its position on the ring. When a node is added or removed, only the keys between the new/removed node and its predecessor are remapped — on average 1/N of all keys, rather than all keys (as with modular hashing). Virtual nodes (vnodes): each physical node gets multiple positions on the ring to improve load balance and allow weighted distribution. Use consistent hashing for: distributed caches (memcached, Redis cluster), sharding database requests, load balancing stateful connections. In Go, implement with a sorted slice of hash positions and binary search (sort.SearchInts). The hashring package on GitHub is a battle-tested implementation.
Code example
package hashring
import (
"crypto/sha256"
"encoding/binary"
"fmt"
"sort"
)
type Ring struct {
vnodes int
points []uint32
nodeMap map[uint32]string
}
func New(vnodes int) *Ring {
return &Ring{vnodes: vnodes, nodeMap: make(map[uint32]string)}
}
func (r *Ring) AddNode(name string) {
for i := range r.vnodes {
h := hash(fmt.Sprintf("%s#%d", name, i))
r.points = append(r.points, h)
r.nodeMap[h] = name
}
sort.Slice(r.points, func(i, j int) bool { return r.points[i] < r.points[j] })
}
func (r *Ring) Get(key string) string {
h := hash(key)
idx := sort.Search(len(r.points), func(i int) bool { return r.points[i] >= h })
if idx == len(r.points) {
idx = 0 // wrap around the ring
}
return r.nodeMap[r.points[idx]]
}
func hash(s string) uint32 {
h := sha256.Sum256([]byte(s))
return binary.BigEndian.Uint32(h[:4])
}
Follow-up
How many virtual nodes per physical node is typical, and what is the trade-off between vnode count and memory overhead?