命令使用说明
我们的搬迁slot 方案不需要辅助工具 和 复杂的命令, 只需要一条命令, 在dst Node节点 执行
cluster setslot importing nodeid [slotlist]
nodeid 是srcNode
在cluster nodes
命令中展示的id , slotslist
是需要搬迁的slots
(假设现在需要从node A
搬迁slot到node B
,那么node B
是dst Node
,node A
是src Node
)
注意这个nodeid
是srcNode
节点的 ,而不是命令接受的节点。
从命令可以看出来3个特点:
- 搬迁异步执行
- 支持多个slot 同时搬
- 搬迁过程不需要像社区版那样
importing
和migrating
状态,并在后面获取key列表等操作
命令是如何工作的
总体工作流程如下图所示:
- 第一步,
dstNode
接受到命令 这个时候 dstNode会做相关检查:
- 检查搬迁任务的的slot是不是已经属于自己
- dstNode搬迁的slot中有没有数据(正常应该为空) 这里
dstNode
会把搬迁任务的slot list
转换成一个bitmap
(16384位的位图),如果某个slot在搬迁任务中,则位图置为1
- 第二步,
dstNode
通知srcNode
dstNode
会从命令的nodeid
解析出会往这个ip发送一个内部命令preparemigrate
,这个命令会把自己的node id
和bitmap
以及kvstore
个数 作为参数传进去
目的是通知srcNode节点 自己的信息以及需要往目标做搬迁的任务
- 第三步,
srcNode
处理命令
srcNode
节点收到后 会做以下检查:
- 命令发的 node id 在node 列表中 能不能查找到
bitmap
中的slot
是不是已经在搬迁任务中bitmap
中的slot
所有者是不是自己,必须是自己负责的slot
才能搬迁给对方- 两者的
kvstore
数是不是相同
一切检查完成后,srcNode
节点后开始切分任务,切分的原则是按照 kvstore切,属于同一个kvstore
的slot
放在一组任务中(kvstore
相同的slot
数据会在底层存放在一起,后面方便一起扫描搬迁) 切完后会把这个任务数组信息组装成json信息发送给dstNode
(如果前面检测有异常也会写-ERR
信息进去)。
这个时候srcNode
切完一个任务 就会调用startTask
接口(在所有条件ok的请况下),startTask
这个接口中任务会进一步按照 10个slot的大小(可设置)来切成sender
子任务,最终放入线程池
这里直接启动srcNode
的任务,是因为需要保证sender
这一方先启动任务,这些任务都会进入cron
调度任务,进入wait状态
等待接收方触发启动进入start
(也就是dstNode)
- 第四步,解析json返回,启动异步任务
dstNode
解析srcNode
发来的json信息, 如果json没有-ERR
一切正常,那么也直接将解析的json信息 传入startTask
接口(这里会传一个flag表示自己是接受方receiver
),
startTask
这个接口中同样会进一步按照 10个10个大小来切成receiver子任务,每个子任务的slots 都转换成个一个bitmap传入接口,最终放入线程池
receiver
子任务启动后会发送ready
命令给sender
,通知sender
开始发送数据(sender
和receiver
的是通过搬迁slot
的bitmap
信息逐一匹配的)
这里启动任务都是异步的,不需要等待
- 第五步,返回客户端命令
dstNode
启动完所有子任务后返回给客户端OK,这时整个命令就返回OK了,上面第一步到第五步这个过程总共一般不到2秒。
和社区版redis搬迁区别
和社区版核心的区别是, 社区版的搬迁是基于key维度搬迁的,搬迁过程中是以key为最小子任务,一个key搬完后可以通过ask 协议
在目标节点访问,整个过程是同步的。
但遇到大key , 社区版比较难解决,同步搬迁容易卡非常久,超过15秒,甚至自动触发切换,把Master判死,Redis会重新选择新的Master,由于migrating状态是不会同步给slave的,所以slave切换成master后,它身上是没有migrating状态的。 一旦migrating状态消除, ASK协议就不能正常工作, 导致访问出错。
我们的搬迁是以slot为维度,不同slot之间可以并发搬迁
总结有如下优点:
- 使用方法简单, 只需要一个命令不需要借助工具
- 异步处理方式 ,通过发送snapshot和binlog 来同步数据, 在搬迁过程中 不会长时间卡住
- 多线程并发, 以及任务大小可以配置,从而比较灵活控制搬迁的压力和速度
缺点:
- 搬迁时候 对请求性能有影响,(搬迁过程需要响应请求的同时做发送snapshot 等操作)
- 搬迁异步过程可控度不高,需要辅助命令来观测搬迁进度
扩容场景
扩容场景中, 新加入的节点可以向多个 master 发送import 命令,一般是让负载大的节点搬迁slot到新节点