sql >> Base de Datos >  >> NoSQL >> Redis

Usando jedis cómo escribir en una ranura/nodo específico en el clúster de redis

Solución 1:
Se encontró una solución para identificar la ranura en la que entrarían las llaves. JedisCluster tiene algunas API para obtenerlo.

int slotNum = JedisClusterCRC16.getSlot(key); - Proporciona el número de ranura de la llave.

Set<HostAndPort> redisClusterNode = new HashSet<HostAndPort>();
redisClusterNode.add(new HostAndPort(hostItem, port));

JedisSlotBasedConnectionHandler connHandler = new 
              JedisSlotBasedConnectionHandler(redisClusterNode, poolConfig, 60);

Jedis jedis = connHandler.getConnectionFromSlot(slotNum);

Esto proporciona el objeto jedis (desde Jedispool internamente) para el nodo específico en el clúster.
Ahora, con el objeto jedis anterior, todos los comandos se pueden canalizar fácilmente para el nodo específico (en el clúster)

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

A pesar de que este enfoque (con JedisCluster) dio el nodo apropiado al que van las claves, esto no me brindó el rendimiento esperado, creo que se debe al procedimiento involucrado en conocer el número de ranura y el nodo (de la ranura).
El procedimiento anterior parece establecer una conexión física con el nodo (en el clúster) cada vez que intentamos obtener el nodo real (jedis) que contiene el número de ranura. Entonces, esto dificulta el rendimiento en caso de que tengamos millones de claves.
Entonces, otro enfoque (a continuación) usando el paquete Lettuce me ayudó a superar esto.

Solución 2:
Paquete Lettuce usado que admite el envío de lotes de comandos en modo clúster.

     <groupId>biz.paluch.redis</groupId>
     <artifactId>lettuce</artifactId>
     <version>4.4.3.Final</version>

Fragmento de código:

RedisClusterClient client = RedisClusterClient.create(RedisURI.create("hostname", "port"));
StatefulRedisClusterConnection<String, String> connection = client.connect();

RedisAdvancedClusterAsyncCommands<String, String> commands = connection.async();
// Disabling auto-flushing
commands.setAutoFlushCommands(false);

List<RedisFuture<?>> futures = new ArrayList<>();
// kvf is of type Map<String, Map<String, String>>
for (Entry<> e : kvf.entrySet())
{
   futures.add(commands.hmset( (String) e.getKey(), (Map<String, String>) 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