Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用绝地武士如何写入redis集群中的特定插槽/节点_Redis_Jedis_Redis Sentinel_Redis Cluster - Fatal编程技术网

使用绝地武士如何写入redis集群中的特定插槽/节点

使用绝地武士如何写入redis集群中的特定插槽/节点,redis,jedis,redis-sentinel,redis-cluster,Redis,Jedis,Redis Sentinel,Redis Cluster,我正在努力提高向redis集群写入数据的性能。 我们计划从redi sentinel模式转向群集模式,以实现可扩展性 但是,与redis sentinel相比,写操作的性能要差得多。我们在redis sentinel中利用了管道,但集群模式不支持管道 所以,我想将所有指向同一节点的密钥分组,并使用管道将批处理发送到该特定节点 所以,我想知道如何知道/计算(在写入集群之前)特定密钥将写入哪个节点/插槽 但是集群模式不支持流水线 错了 对于单个管道,您只能向同一节点的同一连接发送多个命令。它与此节点

我正在努力提高向redis集群写入数据的性能。 我们计划从redi sentinel模式转向群集模式,以实现可扩展性

但是,与redis sentinel相比,写操作的性能要差得多。我们在redis sentinel中利用了管道,但集群模式不支持管道

所以,我想将所有指向同一节点的密钥分组,并使用管道将批处理发送到该特定节点

所以,我想知道如何知道/计算(在写入集群之前)特定密钥将写入哪个节点/插槽

但是集群模式不支持流水线

错了

对于单个管道,您只能向同一节点的同一连接发送多个命令。它与此节点是单个实例还是Redis集群的成员无关

因此,您的问题应该是使用单个管道,我们无法发送多个命令,其中密钥分布在多个插槽上。为了解决这个问题,您希望这些键位于同一插槽中。我们如何才能做到这一点?

如何知道/计算(在写入集群之前)特定密钥将写入哪个节点/插槽

你不需要自己计算。您可以使用
哈希标记
强制多个键成为同一哈希槽的一部分

因此,您只需要使用相同的
哈希标记重命名那些您希望位于同一插槽中的密钥。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()]));