Smart Clients & Redirection
In many distributed systems, a “Load Balancer” sits in front of the database nodes to route traffic. Redis Cluster takes a different approach: The client is responsible for routing.
This removes the bottleneck of a central proxy and allows Redis to achieve millions of operations per second with single-digit millisecond latency.
1. MOVED: The Permanent Redirect
When a client sends a command (e.g., GET user:100) to a node, the node calculates the hash slot.
- If the node owns the slot: It processes the command and returns the result.
- If the node DOES NOT own the slot: It returns a MOVED error.
-MOVED 3999 127.0.0.1:6381
This error tells the client:
- “I don’t have slot 3999.”
- “The node at 127.0.0.1:6381 has it.”
- Action: Please update your local map and go there.
Smart Client Implementation
A “Smart Client” (like Jedis for Java or go-redis for Go) maintains a local Slot Cache. When it receives a MOVED error, it updates this cache so that future requests for slot 3999 go directly to the correct node.
// JedisCluster automatically handles MOVED/ASK errors
try (JedisCluster cluster = new JedisCluster(new HostAndPort("127.0.0.1", 7000))) {
// The client already cached the slots on startup
cluster.set("user:100", "Alice");
// If the topology changes, Jedis catches the MOVED error,
// updates its cache, and retries automatically.
String value = cluster.get("user:100");
}
import "github.com/redis/go-redis/v9"
rdb := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{":7000", ":7001", ":7002"},
})
// The library handles slot mapping internally
err := rdb.Set(ctx, "user:100", "Alice", 0).Err()
// If a MOVED error occurs, go-redis updates its slot map
// and retries the command transparently.
val, err := rdb.Get(ctx, "user:100").Result()
2. ASK: The Temporary Redirect
There is a special case: Resharding. When you are moving data from Node A to Node B, some keys for a slot might be on Node A, while others have already moved to Node B.
If a client asks Node A for a key that has already moved to Node B, Node A returns an ASK error.
-ASK 3999 127.0.0.1:6381
This tells the client:
- “Slot 3999 is currently migrating.”
- “Check 127.0.0.1:6381 for this specific key.”
- Action: Ask that node ONLY for this request. Do NOT update your slot map.
[!IMPORTANT] MOVED vs ASK:
- MOVED: The slot has permanently moved. Update the map.
- ASK: The slot is migrating. Do not update the map yet.
3. Interactive: Redirection Flow
Simulate a client request hitting the wrong node and handling the redirection.
4. Summary
- No Proxies: Clients talk directly to shards.
- MOVED: Permanent redirect. Update your map.
- ASK: Temporary redirect. Follow it once, but don’t update your map.
- Smart Clients: Libraries like Jedis and go-redis handle this complexity automatically.