首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用jedis如何写入redis集群中的特定时隙/节点

使用jedis如何写入redis集群中的特定时隙/节点
EN

Stack Overflow用户
提问于 2018-03-08 18:09:18
回答 2查看 4.1K关注 0票数 6

我试图提高向redis集群写入数据的性能。为了实现可伸缩性,我们计划从redi模式转向集群模式。

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

所以,我想把所有进入同一个节点的密钥分组,然后使用管道将批处理发送到特定的节点。

因此,我想知道如何知道/计算(在编写集群之前)某个特定键将被写入哪个节点/插槽?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-03-12 04:43:18

解决方案1:

找到一个解决方案来识别键将进入的槽。JedisCluster有一些API来获得它。

int slotNum = JedisClusterCRC16.getSlot(key); -提供密钥的插槽号。

代码语言:javascript
复制
Set<HostAndPort> redisClusterNode = new HashSet<HostAndPort>();
redisClusterNode.add(new HostAndPort(hostItem, port));

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

Jedis jedis = connHandler.getConnectionFromSlot(slotNum);

这为集群中的特定节点提供了jedis对象(来自内部Jedispool )。

现在,使用上面的jedis对象,所有命令都可以很容易地用于特定节点(在集群中)。

代码语言:javascript
复制
Pipeline pipeline = jedis.pipelined();
pipeline.multi();
for(Entry<String, Map<String, String>> kvf : kvfs.entrySet()) {
   pipeline.hmset(kvf.getKey(), kvf.getValue());
}
pipeline.exec();

尽管这种方法(使用JedisCluster)给出了键指向的适当节点--这并没有为我提供预期的性能,但我认为这是由于了解时隙号和节点(时隙)所涉及的过程。

每次尝试获取包含时隙号的实际节点(jedis)时,上面的过程似乎都会建立到节点(集群中)的物理连接。所以,这阻碍了我们的性能,万一我们有上百万的钥匙。

因此,另一种使用生菜包的方法(下面)帮助我克服了这一点。

解决方案2:

已使用的生菜包,它支持在群集模式下发送批量命令。

代码语言:javascript
复制
     <groupId>biz.paluch.redis</groupId>
     <artifactId>lettuce</artifactId>
     <version>4.4.3.Final</version>

代码片段:

代码语言:javascript
复制
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()]));

参考文献:https://github.com/lettuce-io/lettuce-core/wiki/Pipelining-and-command-flushing

票数 8
EN

Stack Overflow用户

发布于 2018-03-09 02:05:24

但是集群模式不支持管道

错了!

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

因此,您的问题应该是具有单个管道的,我们不能发送多个命令,其中的密钥分布在多个插槽上。为了解决这个问题,您希望这些密钥位于相同的位置。我们怎样才能做到这一点?

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

你不需要自己计算。您可以使用Hash Tags强制多个键成为同一个散列槽的一部分。

因此,您只需要用相同的Hash Tags重命名这些键,您希望它们位于相同的位置。将user-nameuser-age重命名为{user-id}user-name{user-id}user-age

有关细节,请参见Hash Tags 文档

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49179753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档