Lösung 1:
Es wurde eine Lösung gefunden, um den Steckplatz zu identifizieren, in den die Schlüssel passen würden. JedisCluster hat einige APIs, um es zu bekommen.
int slotNum = JedisClusterCRC16.getSlot(key);
- Liefert die Steckplatznummer des Schlüssels.
Set<HostAndPort> redisClusterNode = new HashSet<HostAndPort>();
redisClusterNode.add(new HostAndPort(hostItem, port));
JedisSlotBasedConnectionHandler connHandler = new
JedisSlotBasedConnectionHandler(redisClusterNode, poolConfig, 60);
Jedis jedis = connHandler.getConnectionFromSlot(slotNum);
Dadurch wird das jedis-Objekt (intern von Jedispool) für den spezifischen Knoten im Cluster bereitgestellt.
Jetzt können mit dem obigen jedis-Objekt alle Befehle einfach für den spezifischen Knoten (im Cluster) weitergeleitet werden
Pipeline pipeline = jedis.pipelined();
pipeline.multi();
for(Entry<String, Map<String, String>> kvf : kvfs.entrySet()) {
pipeline.hmset(kvf.getKey(), kvf.getValue());
}
pipeline.exec();
Trotz dieses Ansatzes (mit JedisCluster) gab ich den entsprechenden Knoten, an den die Schlüssel gehen, dies brachte mir nicht die erwartete Leistung, ich denke, es liegt an der Prozedur, die erforderlich ist, um die Slot-Nummer und den Knoten (des Slots) zu kennen.
Das obige Verfahren scheint jedes Mal eine physische Verbindung zum Knoten (im Cluster) herzustellen, wenn wir versuchen, den tatsächlichen Knoten (Jedis) zu erhalten, der die Steckplatznummer enthält. Dies behindert also die Leistung, falls wir Millionen von Schlüsseln haben.
Also hat mir ein anderer Ansatz (unten) mit dem Lettuce-Paket geholfen, dies zu überwinden.
Lösung 2:
Verwendetes Lettuce-Paket, das das Senden von Befehlsstapeln im Cluster-Modus unterstützt.
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>4.4.3.Final</version>
Codeausschnitt:
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()]));
Siehe:https://github.com/lettuce-io/lettuce-core/wiki/Pipelining-and-command-flushing