Tuesday, 1 November 2016

How to move a single slot in redis cluster

In redis cluster, there are a total of 16384 logical slots, which are divided between multiple masters.
Often, when we need to add nodes to the redis cluster, we need to reshard the data.
This is done by redis-trib.rb utility file provided by redis.
However the redis-trib.rb utility can move N no of slots between masters, but it does not provide a function to move a single slot.
Moving a slot normally involves 3 steps as described here.


  1. setting the destination node to receive a slot.
  2. setting the source node to migrate a slot.
  3. migrating the data from source node to destination node.
  4. communicating source and destination nodes that the destination node is the owner of the slot.

Below is shown an existing cluster where the slots are equally divided between nodes.
Also, each node has some data.



We will try to move a slot, say slot no 102, from redis running on port 7000 to redis running on port 7001
The java code for it is below.



import java.util.List;

import com.google.common.collect.Lists;
import com.lambdaworks.redis.MigrateArgs;
import com.lambdaworks.redis.RedisClient;
import com.lambdaworks.redis.RedisURI;
import com.lambdaworks.redis.api.sync.RedisCommands;
import com.lambdaworks.redis.cluster.models.partitions.ClusterPartitionParser;
import com.lambdaworks.redis.cluster.models.partitions.Partitions;
import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode;
import com.lambdaworks.redis.codec.Utf8StringCodec;
import com.lambdaworks.redis.protocol.CommandArgs;

public class RedisMoveSingleSlot {
public static void main(String[] args){
String sourceHost = "127.0.0.1";
int sourcePort = 7000;
String destHost = "127.0.0.1";
int destPort = 7001;
int slotToMove = 102;
moveSlot(sourceHost, sourcePort, destHost, destPort, slotToMove);
}
private static void moveSlot(String sourceHost, int sourcePort, String destHost, int destPort, int slot) {
// create connections to source and destinations.
RedisClient sourceClient = RedisClient.create(RedisURI.create(sourceHost, sourcePort));
RedisClient destinationClient = RedisClient.create(RedisURI.create(destHost, destPort));
RedisCommands<String, String> source = sourceClient.connect().sync();
RedisCommands<String, String> destination = destinationClient.connect().sync();
// get the source node Id and destination Node Id.
String sourceNodeId = source.clusterMyId();
String destinationNodeId = destination.clusterMyId();

//STEP 1, set destination to be importing slot from source.
destination.clusterSetSlotImporting(slot, sourceNodeId);
//STEP 2, set source to be migrating slot to destination.
source.clusterSetSlotMigrating(slot, destinationNodeId);
// STEP 3 starts, we need to move all the keys from source to destination.
List<String> keys = source.clusterGetKeysInSlot(slot, Integer.MAX_VALUE);
// move keys in batches of 100, 
int keySize = 100;
System.out.println("Slot : " + slot + " : got keys of size : " + keys.size() );
if(keys != null && keys.size() > 0){
List<List<String>> listOfListOfKeys = Lists.partition(keys, keySize);
int noOfKeysMoved = 0;
for(List<String> listOfKeys : listOfListOfKeys){
MigrateArgs<String> migrateArgs = new MigrateArgs<>();
migrateArgs.keys(listOfKeys);
migrateArgs.replace();
CommandArgs<String, String> args1 = new CommandArgs<String, String>(new Utf8StringCodec());
migrateArgs.build(args1);
// migrate the keys from source to destination in db 0(default), and will some timeout set, here set to 5000 secs.
source.migrate(destHost, destPort, 0, 5000000, migrateArgs);
noOfKeysMoved = noOfKeysMoved + listOfKeys.size();
System.out.println("totally moved " + noOfKeysMoved + " for slot " + slot);
}
//Thread.sleep(5000);
}
//STEP 3 finished.

// STEP 4, set cluster set slot on source and destination and close the source and destinations.
source.clusterSetSlotNode(slotdestinationNodeId);

destination.clusterSetSlotNode(slotdestinationNodeId);

source.close();
destination.close();

// STEP 4 done.
System.out.println("Moved slot " + slot);
}
}

After the code is executed, it moved 2 keys(which belonged to slot 102) and slot no 102 from redis on 7000 port to redis on 7002 port.
Below was the output of "cluster nodes" and "dbsize" command on each nodes.
Note that the slot 102 moved. Also the no of keys belonging to redis with 7001 port increased by 2.


2 comments:

  1. I really appreciate your support on this.
    Look forward to hearing from you soon.
    I’m happy to answer your questions, if you have any.


    แจกเครดิตฟรี ฝากถอนง่าย

    แจกเครดิตฟรี ฝากถอนง่าย

    เล่นบาคาร่า

    ReplyDelete
  2. Many thanks for your kind invitation. I’ll join you.
    Would you like to play cards?
    Come to the party with me, please.
    See you soon...

    เล่นบาคาร่า

    เครดิตฟรี

    คาสิโน

    คาสิโนออนไลน์

    ReplyDelete