当前位置:   article > 正文

Redis集群

redis-dump : crossslot keys in request don't hash to the same slot

随着大型网站数据量和对系统可用性要求的提升,单机版的Redis越来越难以满足需要,因此我们需要使用Redis集群来提供服务。

目前主流的Redis集群解决方案有三类,它们都是通过将key分散到不同的redis实例上来提高整体能力, 这种方法称为分片(sharding):

  • 服务端分片: 客户端与集群中任意的节点通信,服务端计算key在哪一个节点上,若不再当前节点上则通知客户端应访问的节点。 典型代表为官方推出的Redis Cluster
  • 客户端分片: 客户端计算key应在集群中的哪一个节点上,并与该节点通信。典型代表为ShardedJedis
  • 代理分片: 客户端与集群中的代理(proxy)通信,代理与节点通信进行操作。典型代表为Codis

单机版的Redis中单条指令的执行总是原子性的,在集群中则难以保证这一性质,某些指令可能无法在集群中使用或者受到限制。

若需要使用这些指令或需要它们保持原子性,可以采用单机版Redis和集群搭配使用的方法。将主要业务部署在集群上,将需要较多支持的服务部署在单机版Redis上。

三种集群实现方式各有有缺,本文分别进行简单介绍它们的特性。本文不会详细介绍三种方式的使用方式,只对其架构和特性进行对比,帮助读者选择合适的解决方案。

基本概念

哈希槽

哈希槽(hash slot)是来自Redis Cluster的概念, 但在各种集群方案都有使用。

哈希槽是一个key的集合,Redis集群共有16384个哈希槽,每个key通过CRC16散列然后对16384进行取模来决定该key应当被放到哪个槽中,集群中的每个节点负责一部分哈希槽。

以有三个节点的集群为例:

  • 节点A包含0到5500号哈希槽
  • 节点B包含5501到11000号哈希槽
  • 节点C包含11001到16384号哈希槽

这样的设计有利于对集群进行横向伸缩,若要添加或移除节点只需要将该节点上的槽转移到其它节点即可。

在某些集群方案中,涉及多个key的操作会被限制在一个slot中,如Redis Cluster中的mget/mset操作。

HashTag

HashTag机制可以影响key被分配到的slot,从而可以使用那些被限制在slot中操作。

HashTag即是用{}包裹key的一个子串,如{user:}1, {user:}2

在设置了HashTag的情况下,集群会根据HashTag决定key分配到的slot, 两个key拥有相同的HashTag:{user:}, 它们会被分配到同一个slot,允许我们使用MGET命令。

通常情况下,HashTag不支持嵌套,即将第一个{和第一个}中间的内容作为HashTag。若花括号中不包含任何内容则会对整个key进行散列,如{}user:

HashTag可能会使过多的key分配到同一个slot中,造成数据倾斜影响系统的吞吐量,务必谨慎使用。

主从模型

几种流行的Redis集群解决方案都没有将一个key写到多个节点中,若某个节点故障则无法访问访问其上的key这显然是不满足集群的分区容错性的。

Redis集群使用主从模型(master-slave)来提高可靠性。每个master节点上绑定若干个slave节点,当master节点故障时集群会推举它的某个slave节点代替master节点。

体验Redis集群

Redis Cluster

为了便于部署本文使用docker部署了一个简单集群:

docker run -i -t -p 7000:7000 -p 7001:7001 -p 7002:7002 -p 7003:7003 -p 7004:7004 -p 7005:7005 -p 7006:7006 -p 7007:7007 grokzen/redis-cluster

打开另一个终端窗口, 启动redis客户端:

redis-cli -c -p 7000

在redis客户端中尝试进行操作:

  1. 127.0.0.1:7000> set a 1
  2. -> Redirected to slot [15495] located at 127.0.0.1:7002
  3. OK
  4. 127.0.0.1:7002> get a
  5. "1"
  6. 127.0.0.1:7002> mset ab 2 ac 3
  7. (error) CROSSSLOT Keys in request don't hash to the same slot
  8. 127.0.0.1:7002> mset {a}b 2 {a}c 3
  9. OK

上述示例中, 执行set a命令时客户端被重定向到了其它节点。

mset ab 2 ac 3命令因为key被分配到不同的slot中导致CROSSSLOT错误,而使用HashTag机制mset {a}b 2 {a}c 3就可以解决这个问题。

更多的内容可以参考Redis Cluster中文文档

ShardedJedis

Jedis是一个流行的Java语言Redis客户端,在Redis官方提供Redis Cluster之前便实现了客户端集群功能。

ShardedJedis使用一致性哈希算法进行数据分片,不支持涉及多个key的命令, 其不支持的命令可以参考MultiKeyCommands

  1. JedisPoolConfig poolConfig = new JedisPoolConfig();
  2. poolConfig.setMaxTotal(2);
  3. poolConfig.setMaxIdle(1);
  4. poolConfig.setMaxWaitMillis(2000);
  5. final String HOST = "127.0.0.1";
  6. JedisShardInfo shardInfo1 = new JedisShardInfo(HOST, 6379);
  7. JedisShardInfo shardInfo2 = new JedisShardInfo(HOST, 6380);
  8. JedisShardInfo shardInfo3 = new JedisShardInfo(HOST, 6381);
  9. ShardedJedisPool jedisPool = new ShardedJedisPool(poolConfig, Arrays.asList(shardInfo1, shardInfo2, shardInfo3));
  10. try(ShardedJedis jedis = jedisPool.getResource()) {
  11. jedis.set("a", "1");
  12. jedis.set("b", "2");
  13. System.out.println(jedis.get("a"));
  14. }

在初始化ShardedJedisPool时设置keyTagPattern,匹配keyTagPattern的key会被分配到同一个实例中。

Codis

Codis是豌豆荚开源的代理式Redis集群解决方案,因为Twemproxy缺乏对弹性伸缩的支持,很多企业选择了经过生产环境检验的Codis。

Codis的安装和使用方法可以参考官方文档, 为了方便起见我们使用ReleaseBinary文件安装Codis-Server和Codis-Proxy。

或者使用第三方开发者制作的Docker镜像:

  1. docker run -d --name="codis" -h "codis" -p 18087:18087 -p 11000:11000 -p 19000:19000 ruo91/codis
  2. docker exec codis /bin/bash codis-start all start

使用redis客户端连接19000端口,尝试进行操作:

  1. 127.0.0.1:19000> set a 1
  2. OK
  3. 127.0.0.1:19000> get a
  4. "1"
  5. 127.0.0.1:19000> mset ab 2 ac 3
  6. OK
  7. 127.0.0.1:19000> mset {a}b 2 {a}c 3
  8. OK

Codis也支持HashTag, 不过Codis已经解决了大多数命令的slot限制。

集群方案对比

协议支持

命令Redis ClusterShardedJedisCodis
mget/mset仅限同一个slot不支持失去原子性
keys仅限同一个slot不支持不支持
scan仅限同一个slot不支持仅限同一个slot(SLOTSSCAN命令)
rename仅限同一个slot不支持不支持
pipeline不支持不支持支持
事务支持相同slot不支持不支持
发布/订阅支持不支持不支持
eval仅限同一slot不支持支持

转载于:https://www.cnblogs.com/Finley/p/8595506.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/794031
推荐阅读
相关标签
  

闽ICP备14008679号