redis cluster可以进行动态扩容,我们可以通过redis-trib.rb脚本add node到集群中,再通过reshard 或者move slot命令进行slot的重新分配或者迁移,本篇将讨论在slot迁移过程中的一些问题。
简单的通过一个例子:加入我们已经完成了add node操作,需要将编号为1,2,3的slot从master A迁移到master B
migrating状态
slot 1 ,2 , 3在master A迁出的时候会标记为migrating状态,如果客户端请求的key落在migrating状态的slot中时,分一下情况讨论。
1、如果key存在该slot上,则成功处理请求,返回给客户端
2、如果key不存在,返回客户端ask,这时候并不会改变客户端中node的映射关系,客户端的下次请求还会指向masterA
3、如果有多个命令操作该key,如果都存在则成功处理,如果都不存在,则返回客户端ASK,如果一部分存在,则返回客户端TRYAGAIN,通知客户端稍后重试,这样当所有的Key都迁移完毕的时候客户端重试请求的时候回得到ASK,然后经过一次重定向就可以获取这批键
importing状态
将slot 1 ,2 ,3迁入到masterB中的时候,状态会被标记为import,如果客户端请求的key落在importing状态的slot中的时候,分一下情况。
- 正常命令会被MOVED重定向,如果是ASKING命令则命令会被执行,从而Key没有在老的节点已经被迁移到新的节点的情况可以被顺利处理;
- 如果Key不存在则新建;
- 没有ASKING的请求和正常请求一样被MOVED,这保证客户端node映射关系出错的情况下不会发生写错;
键空间迁移
键空间迁移是指当满足了槽迁移前提的情况下,我们就可以通过相关命令将槽1、2、3中的键空间从MasterA节点转移到MasterB节点,这个过程真正实现数据转移。相关命令:
MIGRATE
- DUMP
- RESTORE
- DEL
经过上面三步可以将键空间数据迁移,然后再将处于MIGRATING和IMPORTING状态的槽变为常态即可,完成整个重新分片的过程。然而MIGRATE并不是原子的,如果在MIGRATE出现错误的情况可能会导致下面问题:
- 键空间在两个节点都存在;
- 键空间只存在第一个节点;