集群访问

集群访问

客户端在初始化的时候只需要知道一个节点的地址即可,客户端会先尝试向这个节点执行命令,比如“get key”,如果key所在的slot刚好在该节点上,则能够直接执行成功。如果slot不在该节点,则节点会返回MOVED错误,同时把该slot对应的节点告诉客户端。客户端可以去该节点执行命令。目前客户端有两种做法获取数据分布表,一种就是客户端每次根据返回的MOVED信息缓存一个slot对应的节点,但是这种做法在初期会经常造成访问两次集群。还有一种做法是在节点返回MOVED信息后,通过cluster nodes命令获取整个数据分布表,这样就能每次请求到正确的节点,一旦数据分布表发生变化,请求到错误的节点,返回MOVED信息后,重新执行cluster nodes命令更新数据分布表。

在访问集群的时候,节点可能会返回ASK错误。这种错误是在key对应的slot正在进行数据迁移时产生的,这时候向slot的原节点访问,如果key在迁移源节点上,则该次命令能直接执行。如果key不在迁移源节点上,则会返回ASK错误,描述信息会附上迁移目的节点的地址。客户端这时候要先向迁移目的节点发送ASKING命令,然后执行之前的命令。

这些细节一般都会被客户端sdk封装起来,使用者完全感受不到访问的是集群还是单节点。

集群支持hash tags功能,即可以把一类key定位到同一个节点,tag的标识目前支持配置,只能使用{},redis处理hash tag的逻辑也很简单,redis只计算从第一次出现{,到第一次出现}的substring的hash值,substring为空,则仍然计算整个key的值,这样对于foo{}{bar}、{foo}{bar}、foo这些冲突的{},也能取出tag值。使用者需遵循redis的hash tag规范。

127.0.0.1:6379> CLUSTER KEYSLOT foo{hash_tag}
(integer) 2515
127.0.0.1:6379> CLUSTER KEYSLOT fooadfasdf{hash_tag}
(integer) 2515
127.0.0.1:6379> CLUSTER KEYSLOT fooadfasdfasdfadfasdf{hash_tag}
(integer) 2515
集群版本的redis能够支持全部的单机版命令。不过还是有些命令会有些限制。

订阅在使用上与单机版没有任何区别。订阅功能通过集群间共享publish消息实现的,客户端可以向任意一个节点(包括slave节点)订阅消息,然后在一个节点上执行的publish命令,该节点会把该命令传播给集群内的每个节点,这样订阅该消息的客户端就能收到该命令。

redis集群版只使用db0,select命令虽然能够支持select 0。其他的db都会返回错误。
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> select 1
(error) ERR SELECT is not allowed in cluster mode
redis集群版对多key命令的支持,只能支持多key都在同一个slot上,即使多个slot在一个节点上也不行。

127.0.0.1:6379> mget key7 key28
(error) CROSSSLOT Keys in request don't hash to the same slot
事务的支持只能在也一个slot上完成。MULTI命令之后的命令的key必须都在同一个slot上,如果某条命令的key对应不在相同的slot上,则事务直接回滚。迁移的时候,在迁移源节点执行命令的key必须在移原节点上存在,否则事务就会回滚。在迁移目的节点执行的时候需要先执行ASKING命令再执行MULTI命令,这样接下来该slot的命令都能被执行。可以看出,对于单key和相同hash tags的事务,集群还是能很好的支持。

在迁移的时候有个地方需要注意,对于多key命令在迁移目的节点执行时,如果多个key全在该节点上,则命令无法执行。如下所示,key和key14939对应的slot为12539,执行命令的节点是迁移目的节点:

127.0.0.1:6379> asking
OK
127.0.0.1:6379> mget key key14939
(error) TRYAGAIN Multiple keys request during rehashing of slot

猜你喜欢

转载自u011820505.iteye.com/blog/2302605
0条评论
添加一条新回复