Redis
 sql >> Database >  >> NoSQL >> Redis

Usando jedis come scrivere su uno slot/nodo specifico nel cluster redis

Soluzione 1:
Ho trovato una soluzione per identificare lo slot in cui andrebbero le chiavi. JedisCluster ha alcune API per ottenerlo.

int slotNum = JedisClusterCRC16.getSlot(key); - Fornisce il numero di slot della chiave.

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

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

Jedis jedis = connHandler.getConnectionFromSlot(slotNum);

Ciò fornisce l'oggetto jedis (da Jedispool internamente) per il nodo specifico nel cluster.
Ora con l'oggetto jedis di cui sopra tutti i comandi possono essere facilmente pipeline per il nodo specifico (nel cluster)

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

Nonostante questo approccio (con JedisCluster) abbia fornito il nodo appropriato a cui vanno le chiavi, questo non mi ha fornito le prestazioni previste, penso che sia dovuto alla procedura coinvolta nella conoscenza del numero di slot e del nodo (dello slot).
La procedura sopra sembra stabilire una connessione fisica al nodo (nel cluster) ogni volta che proviamo a ottenere il nodo effettivo (jedis) che contiene il numero di slot. Quindi, questo ostacola le prestazioni nel caso in cui abbiamo milioni di chiavi.
Quindi, un altro approccio (sotto) utilizzando il pacchetto Lattuce mi ha aiutato a superare questo problema.

Soluzione 2:
Utilizzato il pacchetto Lattuce che supporta l'invio di batch di comandi in modalità cluster.

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

Frammento di codice:

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()]));

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