Consistent hashing is a staple in distributed systems interviews because it tests both algorithmic thinking and practical engineering judgment. Below are common questions you’ll hear, a short answer you can deliver in under a minute, and the next question an interviewer often asks to dig deeper.
What is consistent hashing and why do we use it?
Consistent hashing maps keys to points on a circle (the hash ring) and each node owns the segment of the ring that follows it clockwise. When you add or remove a node, only the keys that fall in the affected segment move, so the system reshuffles a tiny fraction of data. This property makes scaling and fault‑tolerance cheap compared to naive modulo‑based partitioning, where a single node change forces a full rehash.
How does the hash ring work? (Follow‑up: "Can you sketch it on a whiteboard?")
You hash every possible key to a 0‑360° value (or 0‑2³² range). Each server also gets a hash value; the server is responsible for all keys whose hash is greater than the previous server’s hash and less than or equal to its own. Visually, draw a circle, place a few points for servers, and show a key landing between two points – it belongs to the next server clockwise.
What problem does consistent hashing solve compared to key % N?
Modulo partitioning requires rehashing every key whenever N changes. Consistent hashing limits movement to roughly 1/N of the keys per node change, which dramatically reduces data migration cost and downtime during scaling events.
What are virtual nodes (or replicas) and why are they useful?
A physical node can be represented by multiple points on the ring, each called a virtual node. By spreading a node’s presence, you smooth out uneven key distribution caused by hash function quirks or uneven node capacities. In practice, a few dozen virtual nodes per physical node give a near‑uniform load without much overhead.
How do you choose the number of virtual nodes?
It’s a trade‑off between load balance and lookup cost. More virtual nodes improve balance but increase the size of the ring lookup table and memory usage. In many production systems, engineers start with 100–200 virtual nodes per machine and adjust based on observed skew.
Explain the lookup process for a given key.
- Hash the key to a point on the ring.
- Perform a binary search (or use a sorted map) to find the first node whose hash is greater than the key’s hash.
- If the key’s hash exceeds the greatest node hash, wrap around to the first node. The result is the node responsible for that key.
How does consistent hashing handle node failures?
When a node fails, its virtual nodes disappear from the ring. Keys that mapped to those virtual nodes automatically remap to the next alive node clockwise. This remapping is immediate and requires no coordination, though you may want a background process to rebuild replicas on other nodes for durability.
What are the trade‑offs of using consistent hashing?
- Pros: Minimal data movement on scaling, natural fault tolerance, easy to add heterogeneous capacity via weighted virtual nodes.
- Cons: Slightly higher lookup latency (binary search on a sorted list), extra memory for virtual node tables, and less deterministic placement than range‑based sharding.
How would you implement consistent hashing in code? (Follow‑up: "Show a snippet in Go or Python.")
Below is a concise Python example that captures the core ideas. It uses bisect for fast lookup and stores virtual nodes in a sorted list.
import bisect, hashlib
class ConsistentHash:
def __init__(self, nodes=None, replicas=100):
self.replicas = replicas
self.ring = [] # sorted list of hashes
self.map = {} # hash -> real node
if nodes:
for n in nodes:
self.add_node(n)
def _hash(self, key):
return int(hashlib.md5(key.encode()).hexdigest(), 16)
def add_node(self, node):
for i in range(self.replicas):
h = self._hash(f"{node}:{i}")
self.ring.append(h)
self.map[h] = node
self.ring.sort()
def remove_node(self, node):
to_remove = [h for h, n in self.map.items() if n == node]
for h in to_remove:
self.ring.remove(h)
del self.map[h]
def get_node(self, key):
h = self._hash(key)
idx = bisect.bisect(self.ring, h) % len(self.ring)
return self.map[self.ring[idx]]
This snippet demonstrates the essential steps: hashing, virtual node insertion, and binary‑search lookup.
How would you adapt consistent hashing for weighted nodes?
Assign more virtual nodes to higher‑capacity machines. For example, a node with double the RAM might receive twice as many replicas. The algorithm itself stays unchanged; the weight is reflected in the density of points on the ring.
What are common pitfalls when deploying consistent hashing at scale?
- Hash function bias: Poor hash functions cause clustering. Use a well‑studied function like MD5, SHA‑1, or a fast non‑cryptographic alternative (e.g., MurmurHash).
- Uneven replica distribution: If you hard‑code a small replica count, hot spots appear when the node count is low.
- Stale metadata: Clients must refresh the ring view when nodes join/leave; otherwise they may route to dead nodes.
- Cold start: When a new node joins, it may receive a burst of traffic for keys that suddenly map to it. Warm‑up strategies (gradual traffic shift) mitigate this.
How does consistent hashing compare to other partitioning schemes?
| Scheme | Data movement on scale change | Load balance | Complexity |
|---|---|---|---|
Modulo (key % N) | O(N) (all keys) | Good (if N static) | Low |
| Range sharding | O(N) for re‑balancing ranges | Moderate (depends on range size) | Medium |
| Consistent hashing | ~1/N of keys per change | Excellent (with virtual nodes) | Medium |
| Rendezvous (HRW) hashing | Similar to consistent hashing, but no ring needed | Excellent | Slightly higher per‑lookup cost |
How would you answer a senior‑level follow‑up about durability?
You would discuss coupling consistent hashing with replication. After locating the primary node via the ring, you also write to the next k clockwise nodes. This gives you both load‑balanced placement and built‑in redundancy. Mention that failure detection (e.g., via heartbeats) triggers a re‑replication process to keep the replica factor intact.
How to practice this
How to practice this
- Write the algorithm from scratch in your preferred language. Focus on the hash ring, virtual nodes, and binary‑search lookup.
- Simulate node churn: add and remove nodes repeatedly and measure the fraction of keys that move. Aim for under 10% movement per change.
- Run mock interviews: use Call Assistant to record yourself answering a question, then let the tool surface follow‑up prompts so you can rehearse staying on topic.
FAQ
- Q: Why do we need virtual nodes if we can just add more physical machines? A: Virtual nodes break up each machine’s responsibility into many small slices, smoothing out randomness in the hash function and preventing a single machine from becoming a hotspot.
- Q: Can consistent hashing handle multi‑tenant workloads? A: Yes. By assigning separate virtual node sets per tenant or using weighted replicas, you can guarantee isolation while still benefiting from the same ring.
- Q: How does consistent hashing differ from Rendezvous (HRW) hashing? A: Both provide minimal reshuffling, but HRW selects the node with the highest hash score for a key, eliminating the need for a sorted ring. HRW can be simpler when you have a small, dynamic node list.
- Q: What monitoring should accompany a consistent‑hashing deployment? A: Track key distribution skew, node health heartbeats, and the rate of key migrations during scaling events. Alerts on sudden spikes often indicate mis‑configured replica counts or hash function issues.
Frequently asked questions
Why do we need virtual nodes if we can just add more physical machines?
Virtual nodes break each machine’s responsibility into many small slices, smoothing out randomness in the hash function and preventing a single machine from becoming a hotspot.
Can consistent hashing handle multi-tenant workloads?
Yes. By assigning separate virtual node sets per tenant or using weighted replicas, you can guarantee isolation while still benefiting from the same ring.
How does consistent hashing differ from Rendezvous (HRW) hashing?
Both provide minimal reshuffling, but HRW selects the node with the highest hash score for a key, eliminating the need for a sorted ring. HRW can be simpler when you have a small, dynamic node list.
What monitoring should accompany a consistent-hashing deployment?
Track key distribution skew, node health heartbeats, and the rate of key migrations during scaling events. Alerts on sudden spikes often indicate mis-configured replica counts or hash function issues.
#concept questions#consistent hashing#distributed systems#interview prep#algorithm design