使用绝地武士如何写入redis集群中的特定插槽/节点
我正在努力提高向redis集群写入数据的性能。 我们计划从redi sentinel模式转向群集模式,以实现可扩展性 但是,与redis sentinel相比,写操作的性能要差得多。我们在redis sentinel中利用了管道,但集群模式不支持管道 所以,我想将所有指向同一节点的密钥分组,并使用管道将批处理发送到该特定节点 所以,我想知道如何知道/计算(在写入集群之前)特定密钥将写入哪个节点/插槽 但是集群模式不支持流水线 错了强> 对于单个管道,您只能向同一节点的同一连接发送多个命令。它与此节点是单个实例还是Redis集群的成员无关 因此,您的问题应该是使用单个管道,我们无法发送多个命令,其中密钥分布在多个插槽上。为了解决这个问题,您希望这些键位于同一插槽中。我们如何才能做到这一点? 如何知道/计算(在写入集群之前)特定密钥将写入哪个节点/插槽 你不需要自己计算。您可以使用使用绝地武士如何写入redis集群中的特定插槽/节点,redis,jedis,redis-sentinel,redis-cluster,Redis,Jedis,Redis Sentinel,Redis Cluster,我正在努力提高向redis集群写入数据的性能。 我们计划从redi sentinel模式转向群集模式,以实现可扩展性 但是,与redis sentinel相比,写操作的性能要差得多。我们在redis sentinel中利用了管道,但集群模式不支持管道 所以,我想将所有指向同一节点的密钥分组,并使用管道将批处理发送到该特定节点 所以,我想知道如何知道/计算(在写入集群之前)特定密钥将写入哪个节点/插槽 但是集群模式不支持流水线 错了 对于单个管道,您只能向同一节点的同一连接发送多个命令。它与此节点
哈希标记
强制多个键成为同一哈希槽的一部分
因此,您只需要使用相同的哈希标记重命名那些您希望位于同一插槽中的密钥。e、 g.将用户名
和用户年龄
重命名为{user id}用户名
和{user id}用户年龄
有关详细信息,请参阅哈希标记。解决方案1:
找到了一个解决方案来确定钥匙将进入的插槽。JedisCluster有一些API来获取它
int slotNum=JedisClusterCRC16.getSlot(键)代码>
-提供密钥的插槽号
Set<HostAndPort> redisClusterNode = new HashSet<HostAndPort>();
redisClusterNode.add(new HostAndPort(hostItem, port));
JedisSlotBasedConnectionHandler connHandler = new
JedisSlotBasedConnectionHandler(redisClusterNode, poolConfig, 60);
Jedis jedis = connHandler.getConnectionFromSlot(slotNum);
Set redisClusterNode=new HashSet();
添加(新主机和端口(主机项,端口));
JedisSlotBasedConnectionHandler connHandler=新建
JedisSlotBasedConnectionHandler(redisClusterNode,poolConfig,60);
绝地武士=connHandler.getConnectionFromSlot(slotNum);
这为集群中的特定节点提供了绝地对象(内部来自绝地spool)
现在使用上述绝地对象,所有命令都可以很容易地通过管道传输到特定节点(集群中)
Pipeline-Pipeline=jedis.pipelined();
pipeline.multi();
对于(条目kvf:kvfs.entrySet()){
hmset(kvf.getKey(),kvf.getValue());
}
pipeline.exec();
尽管这种方法(使用JedisCluster)给出了密钥指向的适当节点,但这并没有为我提供预期的性能,我认为这是由于知道插槽编号和节点(插槽的)所涉及的过程。
每当我们试图获取包含插槽号的实际节点(绝地)时,上述过程似乎都会建立到节点(集群中)的物理连接。因此,如果我们有数百万个密钥,这会影响性能。
因此,另一种使用莴苣包装的方法(如下)帮助我克服了这一问题
解决方案2:
使用了支持以群集模式发送批命令的软件包
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>4.4.3.Final</version>
biz.paluch.redis
为什么说集群模式不支持管道
是错误的?Redis集群和单实例Redis都支持管道当且仅当密钥属于同一节点/插槽时。是的,但对于JedisCLuster的用户,JedisCLuster不支持管道(因为它不提供aby管道对象)
管道化意味着在单个连接上发送多个命令
*我们是否在群集模式下获得单连接?-是的,我们有
*但是,JedisCluster模式API是否为该单一连接提供管道不,没有
因此,从用户角度来看,JedisCluster模式不支持管道
但是,确实有一些方法(解决办法)可以在集群模式下实现管道(有一些注意事项)。我在这里的用例不仅仅是将密钥(具有相同前缀)发送到相同的节点。但是,我的用例是要知道到同一节点的所有键,这样我就可以将我的所有命令(在所有键上)通过管道传输到该特定节点。
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>4.4.3.Final</version>
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()]));