Using jedis how to write to a specific slot/node in redis cluster

前端 未结 2 358
逝去的感伤
逝去的感伤 2021-01-14 17:53

I\'m trying to improve the performance of writing data to redis cluster. We are planning to move from redi-sentinel to cluster mode for scalability.

But, the perfor

2条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-01-14 18:57

    Solution 1:
    Found a solution to identify the slot to which keys would go into. JedisCluster has some APIs to get it.

    int slotNum = JedisClusterCRC16.getSlot(key); - Provides the slot number of the key.

    Set redisClusterNode = new HashSet();
    redisClusterNode.add(new HostAndPort(hostItem, port));
    
    JedisSlotBasedConnectionHandler connHandler = new 
                  JedisSlotBasedConnectionHandler(redisClusterNode, poolConfig, 60);
    
    Jedis jedis = connHandler.getConnectionFromSlot(slotNum);
    

    This provides the jedis object (from Jedispool internally) for the specific node in the cluster.
    Now with the above jedis object all commands can be easily pipelined for the specific node (in cluster)

    Pipeline pipeline = jedis.pipelined();
    pipeline.multi();
    for(Entry> kvf : kvfs.entrySet()) {
       pipeline.hmset(kvf.getKey(), kvf.getValue());
    }
    pipeline.exec();
    

    Despite this approach (with JedisCluster) gave the appropriate node to which the keys go to this didn't provide me the expected performance, I think it's due to the procedure involved in knowing slot number and node (of the slot).
    Above procedure seems to establish a physical connection to the node (in cluster) every time we try to get the actual node (jedis) that contains the slot number. So, this hinders the performance in-case we have millions of keys.
    So, another approach (below) using Lettuce package helped me to over come this.


    Solution 2:
    Used Lettuce package that supports sending batch of commands in cluster mode.

         biz.paluch.redis
         lettuce
         4.4.3.Final
    

    Code snippet:

    RedisClusterClient client = RedisClusterClient.create(RedisURI.create("hostname", "port"));
    StatefulRedisClusterConnection connection = client.connect();
    
    RedisAdvancedClusterAsyncCommands commands = connection.async();
    // Disabling auto-flushing
    commands.setAutoFlushCommands(false);
    
    List> futures = new ArrayList<>();
    // kvf is of type Map>
    for (Entry<> e : kvf.entrySet())
    {
       futures.add(commands.hmset( (String) e.getKey(), (Map) e.getValue()));
    }
    // write all commands to the transport layer
    commands.flushCommands();
    // synchronization example: Wait until all futures complete
    LettuceFutures.awaitAll(10, TimeUnit.SECONDS,
    futures.toArray(new RedisFuture[futures.size()]));
    

    Ref: https://github.com/lettuce-io/lettuce-core/wiki/Pipelining-and-command-flushing


提交回复
热议问题