命令使用说明

我们的搬迁slot 方案不需要辅助工具 和 复杂的命令, 只需要一条命令, 在dst Node节点 执行

  1. cluster setslot importing nodeid [slotlist]

nodeid 是srcNodecluster nodes命令中展示的id , slotslist是需要搬迁的slots (假设现在需要从node A搬迁slot到node B,那么node Bdst Node,node Asrc Node)

注意这个nodeidsrcNode节点的 ,而不是命令接受的节点。

从命令可以看出来3个特点:

  • 搬迁异步执行
  • 支持多个slot 同时搬
  • 搬迁过程不需要像社区版那样importingmigrating状态,并在后面获取key列表等操作

命令是如何工作的

总体工作流程如下图所示: migrate_command

  • 第一步,dstNode接受到命令 这个时候 dstNode会做相关检查:
  1. 检查搬迁任务的的slot是不是已经属于自己
  2. dstNode搬迁的slot中有没有数据(正常应该为空) 这里dstNode会把搬迁任务的slot list转换成一个bitmap(16384位的位图),如果某个slot在搬迁任务中,则位图置为1
  • 第二步,dstNode通知srcNode dstNode会从命令的nodeid解析出会往这个ip发送一个内部命令preparemigrate,这个命令会把自己的node idbitmap以及kvstore个数 作为参数传进去

目的是通知srcNode节点 自己的信息以及需要往目标做搬迁的任务

  • 第三步,srcNode处理命令

srcNode节点收到后 会做以下检查:

  1. 命令发的 node id 在node 列表中 能不能查找到
  2. bitmap中的slot是不是已经在搬迁任务中
  3. bitmap中的slot所有者是不是自己,必须是自己负责的slot才能搬迁给对方
  4. 两者的kvstore数是不是相同

一切检查完成后,srcNode节点后开始切分任务,切分的原则是按照 kvstore切,属于同一个kvstoreslot放在一组任务中(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开始发送数据(senderreceiver的是通过搬迁slotbitmap信息逐一匹配的)

这里启动任务都是异步的,不需要等待

  • 第五步,返回客户端命令

dstNode启动完所有子任务后返回给客户端OK,这时整个命令就返回OK了,上面第一步到第五步这个过程总共一般不到2秒。

和社区版redis搬迁区别

和社区版核心的区别是, 社区版的搬迁是基于key维度搬迁的,搬迁过程中是以key为最小子任务,一个key搬完后可以通过ask 协议在目标节点访问,整个过程是同步的

但遇到大key , 社区版比较难解决,同步搬迁容易卡非常久,超过15秒,甚至自动触发切换,把Master判死,Redis会重新选择新的Master,由于migrating状态是不会同步给slave的,所以slave切换成master后,它身上是没有migrating状态的。 一旦migrating状态消除, ASK协议就不能正常工作, 导致访问出错。

我们的搬迁是以slot为维度,不同slot之间可以并发搬迁

总结有如下优点:

  1. 使用方法简单, 只需要一个命令不需要借助工具
  2. 异步处理方式 ,通过发送snapshot和binlog 来同步数据, 在搬迁过程中 不会长时间卡住
  3. 多线程并发, 以及任务大小可以配置,从而比较灵活控制搬迁的压力和速度

缺点:

  1. 搬迁时候 对请求性能有影响,(搬迁过程需要响应请求的同时做发送snapshot 等操作)
  2. 搬迁异步过程可控度不高,需要辅助命令来观测搬迁进度

扩容场景

扩容场景中, 新加入的节点可以向多个 master 发送import 命令,一般是让负载大的节点搬迁slot到新节点 migrate_command