Rebalancing Redis Cluster slots online is less about moving data and more about rearranging the addresses where that data lives, without dropping a single connection.

Let’s watch it happen. Imagine a three-node Redis Cluster: redis-node-1 (master), redis-node-2 (master), and redis-node-3 (master). Each master is responsible for a set of hash slots, which are essentially numerical identifiers for your keys.

Here’s how we might start:

redis-cli -c -p 7001 cluster slots

This command, run against any node in the cluster, shows the current slot distribution. You’ll see output like:

127.0.0.1:7001 is not the cluster primary. Redirected to 127.0.0.1:7002
127.0.0.1:7002 (master)
  0) 1) 0       # Slot ID
     2) 127.0.0.1 # Master IP
     3) 7002      # Master Port
     4) 127.0.0.1 # Slave IP
     5) 7003      # Slave Port
  1) 2) 5461
     2) 127.0.0.1
     3) 7002
     4) 127.0.0.1
     5) 7003
  2) 3) 10922
     2) 127.0.0.1
     3) 7002
     4) 127.0.0.1
     5) 7003
127.0.0.1:7003 (master)
  0) 1) 5462
     2) 127.0.0.1
     3) 7003
     4) 127.0.0.1
     5) 7001
  1) 2) 10923
     2) 127.0.0.1
     3) 7003
     4) 127.0.0.1
     5) 7001
  2) 3) 16383
     2) 127.0.0.1
     3) 7003
     4) 127.0.0.1
     5) 7001
127.0.0.1:7001 (master)
  0) 1) 10923
     2) 127.0.0.1
     3) 7001
     4) 127.0.0.1
     5) 7002
  1) 2) 5462
     2) 127.0.0.1
     3) 7001
     4) 127.0.0.1
     5) 7002
  2) 3) 0
     2) 127.0.0.1
     3) 7001
     4) 127.0.0.1
     5) 7002

(Note: The slot distribution above is simplified for clarity; in a real cluster, slots are contiguous and assigned to masters. The cluster slots output shows ranges. The example above shows how slots can be distributed, but for resharding, we’re interested in moving them.)

The problem arises when one node has significantly more data (and thus more slots) than others, or when you add new nodes and want to distribute the load. We want to move a range of slots from redis-node-3 to redis-node-1.

First, we need a new node ready to receive. Let’s say we’ve added redis-node-4 as a master, and we want to eventually move slots to it. For now, we’ll rebalance between existing masters. Let’s move slots from redis-node-3 to redis-node-1.

The core command is CLUSTER SETSLOT. But it’s not that simple. You don’t just tell a slot to move. You orchestrate a multi-phase process.

Phase 1: Preparing the Destination

We tell redis-node-1 that it will be responsible for a range of slots, say 1000-1999, but it shouldn’t accept writes for them yet.

redis-cli -c -p 7001 cluster setslot 1000-1999 stable master 7001

This command, run against the destination master (redis-node-1 on port 7001), marks these slots as "stable" for redis-node-1. This means redis-node-1 is now aware it should own these slots, but it’s not yet the active owner.

Phase 2: Migrating the Data

Now, we tell the source master (redis-node-3 on port 7003) to start migrating the actual data for those slots.

redis-cli -c -p 7003 cluster setslot 1000-1999 migrating 7001

This command, run against the source master (redis-node-3), flags the slots as "migrating" and specifies the IP and port of the destination master (7001). When a client tries to access a key within this slot range, redis-node-3 will:

  1. Check if the key exists locally. If yes, it serves it.
  2. If the key doesn’t exist locally, it redirects the client to redis-node-1 (the target IP/port) to fetch the key.
  3. Crucially, when redis-node-1 receives a request for a key it doesn’t have, it will pull that key from redis-node-3. This is the actual data movement.

This process continues until all keys in the specified slot range have been migrated. You can monitor this using CLUSTER COUNT-FAILURE-ATTEMPTS or by observing CLUSTER NODES for changes in slot state.

Phase 3: Completing the Migration

Once all data is moved, we tell the source master (redis-node-3) to stop handling these slots.

redis-cli -c -p 7003 cluster setslot 1000-1999 node

This command, run against the source master, tells it that these slots are no longer its responsibility.

Phase 4: Activating the Destination

Finally, we tell the destination master (redis-node-1) that it can now actively own these slots.

redis-cli -c -p 7001 cluster setslot 1000-1999 master

This command, run against the destination master, marks the slots as "master" for redis-node-1. From this point on, redis-node-1 will accept writes for these slots directly and will no longer redirect to the old owner.

The whole process is orchestrated by the redis-cli CLUSTER commands, which communicate with the cluster’s internal state machine. The key is that clients are continuously redirected, and during the "migrating" phase, the source node forwards requests and the destination node actively pulls data, ensuring no data loss and minimal downtime.

The magic of resharding lies in the MIGRATING and IMPORTING states. When a slot is MIGRATING from node A to node B, node A will reply to clients requesting keys in that slot with MOVED errors, directing them to node B. Node B, upon receiving this MOVED request, will then pull the actual key from node A. Conversely, if a slot is IMPORTING to node A from node B, node A might receive requests for keys it doesn’t have yet. It will then respond with ASK errors, directing the client to node B. The client must then re-issue the command to node B, which will fetch the data and send it back to node A. This dual mechanism ensures data is transferred and clients are always pointed to the correct node, even during the transition.

After resharding, you’ll often find yourself needing to reconfigure the cluster’s cluster-announce-ip and cluster-announce-port on your nodes if you’ve changed network configurations or added new nodes, to ensure the cluster members correctly discover each other.

Want structured learning?

Take the full Redis course →