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.

  1. If the node owns the slot: It processes the command and returns the result.
  2. If the node DOES NOT own the slot: It returns a MOVED error.
Redis Protocol
-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.

📱
Smart Client
Map: Outdated
Node 1
Slot 0-5000
Node 2
Slot 5001-16384
> Ready to send request.

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.