Lösning 1:
Hittade en lösning för att identifiera den plats som nycklarna skulle gå in i. JedisCluster har några API:er för att få det.
int slotNum = JedisClusterCRC16.getSlot(key);
- Ger nyckelns kortnummer.
Set<HostAndPort> redisClusterNode = new HashSet<HostAndPort>();
redisClusterNode.add(new HostAndPort(hostItem, port));
JedisSlotBasedConnectionHandler connHandler = new
JedisSlotBasedConnectionHandler(redisClusterNode, poolConfig, 60);
Jedis jedis = connHandler.getConnectionFromSlot(slotNum);
Detta tillhandahåller jedis-objektet (från Jedispool internt) för den specifika noden i klustret.
Nu med ovanstående jedis-objekt kan alla kommandon enkelt pipelineras för den specifika noden (i klustret)
Pipeline pipeline = jedis.pipelined();
pipeline.multi();
for(Entry<String, Map<String, String>> kvf : kvfs.entrySet()) {
pipeline.hmset(kvf.getKey(), kvf.getValue());
}
pipeline.exec();
Trots att detta tillvägagångssätt (med JedisCluster) gav den lämpliga noden till vilken nycklarna går till, gav detta mig inte den förväntade prestandan, jag tror att det beror på proceduren som är involverad i att känna till lucknummer och nod (för luckan).
Ovanstående procedur verkar upprätta en fysisk anslutning till noden (i klustret) varje gång vi försöker få fram den faktiska noden (jedis) som innehåller slotnumret. Så detta hindrar prestandan om vi har miljontals nycklar.
Så, ett annat tillvägagångssätt (nedan) med salladspaket hjälpte mig att komma över detta.
Lösning 2:
Använt salladspaket som stöder att skicka batch av kommandon i klusterläge.
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>4.4.3.Final</version>
Kodavsnitt:
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