接上篇文章,以下介绍redis cluster的常用操作:set-timeout 节点间心跳超时时间、call 、import、reshard、rebalance、add-node、del-node。
set-timeout用来设置集群节点间心跳连接的超时时间,单位是毫秒,不得小于100毫秒,因为100毫秒对于心跳时间来说太短了。该命令修改是节点配置参数cluster-node-timeout,默认是15000毫秒。通过该命令,可以给每个节点设置超时时间,设置的方式使用config set命令动态设置,然后执行config rewrite命令将配置持久化保存到硬盘。以下是示例:
[root@cache01 src]# redis-cli --cluster set-timeout 192.168.75.187:7001 30000
call命令可以用来在集群的全部节点执行相同的命令。call命令也是需要通过集群的一个节点地址,连上整个集群,然后在集群的每个节点执行该命令。
[root@cache01 src]# redis-cli --cluster call 192.168.75.187:7001 get name
运行效果如下:
import命令可以把外部的redis节点数据导入集群。如下示例:
[root@cache01 src]# redis-cli --cluster import 192.168.75.187:7005 --cluster-from 192.168.75.187:7002
上面的命令是把 192.168.75.187:7002上的数据导入到 192.168.75.187:7005这个节点所在的集群
导入的流程如下:
1、通过load_cluster_info_from_node方法加载集群信息,check_cluster方法检查集群是否健康;
2、连接外部redis节点,如果外部节点开启了cluster_enabled,则提示错误;
3、通过scan命令遍历外部节点,一次获取1000条数据;
4、遍历这些key,计算出key对应的slot;
5、执行migrate命令,源节点是外部节点,目的节点是集群slot对应的节点,如果设置了–copy参数,则传递copy参数,如果设置了–replace,则传递replace参数;
6、不停执行scan命令,直到遍历完全部的key;
7、至此完成整个迁移流程。
这中间如果出现异常,程序就会停止。没使用--copy模式,则可以重新执行import命令,使用--copy的话,最好清空新的集群再导入一次。
import命令更适合离线的把外部redis数据导入,在线导入的话最好使用更专业的导入工具,以slave的方式连接redis节点去同步节点数据应该是更好的方式。
5.8.9. 注意事项:集群创建时 replicas 参数指定情况
使用 --replicas 1 参数时,如果节点数量少于六个,会报如下错误:
*** ERROR: Invalid configuration for cluster creation.
*** Redis Cluster requires at least 3 master nodes.
*** This is not possible with 5 nodes and 1 replicas per node.
*** At least 6 nodes are required.
使用 --replicas 1 参数时,如果节点数量 大于六个,且为单数时。
这样会造成某个master拥有两个salve
reshard命令可以在线把集群的一些slot从集群原来slot负责节点迁移到新的节点,利用reshard可以完成集群的在线横向扩容和缩容。
reshard的参数很多,下面来一一解释一番:
reshard host:port
–cluster-from
–cluster-to
–cluster-slots
–cluster-yes
–cluster-timeout
–cluster-pipeline
–cluster-replace
命令 | 说明 |
---|---|
host:port | 这个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口。 |
–cluster-from | 需要从哪些源节点上迁移slot,可从多个源节点完成迁移,以逗号隔开,传递的是节点的node id,还可以直接传递–cluster-from all,这样源节点就是集群的所有节点,不传递该参数的话,则会在迁移过程中提示用户输入。 |
–cluster-to | slot需要迁移的目的节点的node id,目的节点只能填写一个,不传递该参数的话,则会在迁移过程中提示用户输入。 |
–cluster-slots | 需要迁移的slot数量,不传递该参数的话,则会在迁移过程中提示用户输入。 |
–cluster-yes | 设置该参数,可以在打印执行reshard计划的时候,提示用户输入yes确认后再执行reshard。 |
–timeout | 设置migrate命令的超时时间。 |
–cluster-pipeline | 定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10。 |
–cluster-replace |
迁移的流程如下:
1、通过load_cluster_info_from_node方法装载集群信息。
2、执行check_cluster方法检查集群是否健康。只有健康的集群才能进行迁移。
3、获取需要迁移的slot数量,用户没传递–cluster-slots参数,则提示用户手动输入。
4、获取迁移的目的节点,用户没传递–cluster-to参数,则提示用户手动输入。此处会检查目的节点必须为master节点。
5、获取迁移的源节点,用户没传递–cluster-from参数,则提示用户手动输入。此处会检查源节点必须为master节点。–cluster-from all的话,源节点就是除了目的节点外的全部master节点。这里为了保证集群slot分配的平均,建议传递–cluster-from all。
6、执行compute_reshard_table方法,计算需要迁移的slot数量如何分配到源节点列表,采用的算法是按照节点负责slot数量由多到少排序,计算每个节点需要迁移的slot的方法为:迁移slot数量 * (该源节点负责的slot数量 / 源节点列表负责的slot总数)。这样算出的数量可能不为整数,这里代码用了下面的方式处理:
n = (numslots/source_tot_slots*s.slots.length)
if i == 0
n = n.ceil
else
n = n.floor
这样的处理方式会带来最终分配的slot与请求迁移的slot数量不一致,这是一个个BUG。
7、打印出reshard计划,如果用户没传–cluster-yes,就提示用户确认计划。
8、根据reshard计划,一个个slot的迁移到新节点上,迁移使用move_slot方法,该方法被很多命令使用。move_slot方法传递dots为true和pipeline数量。
9、至此,就完成了全部的迁移任务。
下面看下一次reshard的执行结果:
[root@cache01 src]# redis-cli --cluster reshard 192.168.75.187:7001 --cluster-from all --cluster-to c276f98fb8f6b74cccceb3eb7399702fa6644cd9 --cluster-slots 11
>>> Performing Cluster Check (using node 192.168.75.187:7001)
M: 97901b9d1281fb8b27b26898340ec1682dfffdba 192.168.75.187:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: ac47bd2d21c50500cc59c0f35720801f49e8cbba 192.168.75.187:7005
slots: (0 slots) slave
replicates 97901b9d1281fb8b27b26898340ec1682dfffdba
M: c276f98fb8f6b74cccceb3eb7399702fa6644cd9 192.168.75.187:7003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 3605efaeea1afcfd373f17181cf09a02915aa098 192.168.75.187:7004
slots: (0 slots) slave
replicates c276f98fb8f6b74cccceb3eb7399702fa6644cd9
S: e59bc95e8fadbcc1acaf95ada1621b8594c48007 192.168.75.187:7006
slots: (0 slots) slave
replicates d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
M: d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143 192.168.75.187:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
Ready to move 11 slots.
Source nodes:
M: 97901b9d1281fb8b27b26898340ec1682dfffdba 192.168.75.187:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143 192.168.75.187:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
Destination node:
M: c276f98fb8f6b74cccceb3eb7399702fa6644cd9 192.168.75.187:7003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
Resharding plan:
Moving slot 5461 from d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
Moving slot 5462 from d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
Moving slot 5463 from d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
Moving slot 5464 from d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
Moving slot 5465 from d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
Moving slot 5466 from d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
Moving slot 0 from 97901b9d1281fb8b27b26898340ec1682dfffdba
Moving slot 1 from 97901b9d1281fb8b27b26898340ec1682dfffdba
Moving slot 2 from 97901b9d1281fb8b27b26898340ec1682dfffdba
Moving slot 3 from 97901b9d1281fb8b27b26898340ec1682dfffdba
Moving slot 4 from 97901b9d1281fb8b27b26898340ec1682dfffdba
Do you want to proceed with the proposed reshard plan (yes/no)? yes
Moving slot 5461 from 192.168.75.187:7002 to 192.168.75.187:7003:
Moving slot 5462 from 192.168.75.187:7002 to 192.168.75.187:7003:
Moving slot 5463 from 192.168.75.187:7002 to 192.168.75.187:7003:
Moving slot 5464 from 192.168.75.187:7002 to 192.168.75.187:7003:
Moving slot 5465 from 192.168.75.187:7002 to 192.168.75.187:7003:
Moving slot 5466 from 192.168.75.187:7002 to 192.168.75.187:7003:
Moving slot 0 from 192.168.75.187:7001 to 192.168.75.187:7003:
Moving slot 1 from 192.168.75.187:7001 to 192.168.75.187:7003:
Moving slot 2 from 192.168.75.187:7001 to 192.168.75.187:7003:
Moving slot 3 from 192.168.75.187:7001 to 192.168.75.187:7003:
Moving slot 4 from 192.168.75.187:7001 to 192.168.75.187:7003:
[root@cache01 src]#
move_slot方法可以在线将一个slot的全部数据从源节点迁移到目的节点,fix、reshard、rebalance都需要调用该方法迁移slot。
move_slot接受下面几个参数:
1、pipeline:设置一次从slot上获取多少个key。
2、quiet:迁移会打印相关信息,设置quiet参数,可以不用打印这些信息。
3、cold:设置cold,会忽略执行importing和migrating。
4、dots:设置dots,则会在迁移过程打印迁移key数量的进度。
5、update:设置update,则会更新内存信息,方便以后的操作。
move_slot流程如下:
1、如果没有设置cold,则对源节点执行cluster importing命令,对目的节点执行migrating命令。fix的时候有可能importing和migrating已经执行过来,所以此种场景会设置cold。
2、通过cluster getkeysinslot命令,一次性获取远节点迁移slot的pipeline个key的数量.
3、对这些key执行migrate命令,将数据从源节点迁移到目的节点。
4、如果migrate出现异常,在fix模式下,BUSYKEY的异常,会使用migrate的replace模式再执行一次,BUSYKEY表示目的节点已经有该key了,replace模式可以强制替换目的节点的key。不是fix模式就直接返回错误了。
5、循环执行cluster getkeysinslot命令,直到返回的key数量为0,就退出循环。
6、如果没有设置cold,对每个节点执行cluster setslot命令,把slot赋给目的节点。
7、如果设置update,则修改源节点和目的节点的slot信息。
8、至此完成了迁移slot的流程。
rebalance命令
rebalance命令可以根据用户传入的参数平衡集群节点的slot数量,rebalance功能非常强大,可以传入的参数很多,以下是rebalance的参数列表和命令示例。
rebalance host:port --cluster-weight
--cluster-use-empty-masters --cluster-timeout --cluster-simulate --cluster-pipeline --cluster-threshold --cluster-replace
[root@cache01 src]# redis-cli --cluster rebalance 192.168.75.187:7001 --cluster-threshold 1 --cluster-weight c276f98fb8f6b74cccceb3eb7399702fa6644cd9=5 d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143=5 --cluster-use-empty-masters --cluster-simulate
>>> Performing Cluster Check (using node 192.168.75.187:7001)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Rebalancing across 3 nodes. Total weight = 11.00
Moving 1991 slots from 192.168.75.187:7001 to 192.168.75.187:7002
#######################################################################################################################################################
Moving 1976 slots from 192.168.75.187:7001 to 192.168.75.187:7003
########################################################
[root@cache01 src]#
以下是各个参数的用法:
参数 | 用法 |
---|---|
host:port | 这个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口。 |
–cluster-weight |
节点的权重,格式为node_id=weight,可为多个节点分配权重。没有传递–weight的节点的权重默认为1。 |
–cluster-use-empty-masters | rebalance是否考虑没有节点的master,默认没有分配slot节点的master是不参与rebalance的,设置–cluster-use-empty-masters可以让没有分配slot的节点参与rebalance。 |
–cluster-timeout | 设置migrate命令的超时时间。 |
–cluster-simulate | 设置该参数,可以模拟rebalance操作,提示用户会迁移哪些slots,而不会真正执行迁移操作。 |
–cluster-pipeline | 与reshard的pipeline参数一样,定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10。 |
–cluster-threshold | 只有节点需要迁移的slot阈值超过threshold,才会执行rebalance操作。具体计算方法可以参考下面的rebalance命令流程的第四步。 |
–cluster-replace |
rebalance命令流程如下:
1、load_cluster_info_from_node方法先加载集群信息。
2、计算每个master的权重,根据参数–weight ,为每个设置的节点分配权重,没有设置的节点,则权重默认为1。
3、根据每个master的权重,以及总的权重,计算自己期望被分配多少个slot。计算的方式为:总slot数量 * (自己的权重 / 总权重)。
4、计算每个master期望分配的slot是否超过设置的阈值,即–threshold 设置的阈值或者默认的阈值。计算的方式为:先计算期望移动节点的阈值,算法为:
(100-(100.0*expected/n.slots.length)).abs
如果计算出的阈值没有超出设置阈值,则不需要为该节点移动slot。只要有一个master的移动节点超过阈值,就会触发rebalance操作。
5、如果触发了rebalance操作。那么就开始执行rebalance操作,先将每个节点当前分配的slots数量减去期望分配的slot数量获得balance值。将每个节点的balance从小到大进行排序获得sn数组。
6、用dst_idx和src_idx游标分别从sn数组的头部和尾部开始遍历。目的是为了把尾部节点的slot分配给头部节点。
sn数组保存的balance列表排序后,负数在前面,正数在后面。负数表示需要有slot迁入,所以使用dst_idx游标,正数表示需要有slot迁出,所以使用src_idx游标。理论上sn数组各节点的balance值加起来应该为0,不过由于在计算期望分配的slot的时候只是使用直接取整的方式,所以可能出现balance值之和不为0的情况,balance值之和不为0即为节点不平衡的slot数量,由于slot总数有16384个,不平衡数量相对于总数,基数很小,所以对rebalance流程影响不大。
7、获取sn[dst_idx]和sn[src_idx]的balance值较小的那个值,该值即为需要从sn[src_idx]节点迁移到sn[dst_idx]节点的slot数量。
8、接着通过compute_reshard_table方法计算源节点的slot如何分配到源节点列表。这个方法在reshard流程中也有调用,具体步骤可以参考reshard流程的第六步。
9、如果是simulate模式,则只是打印出迁移列表。
10、如果没有设置simulate,则执行move_slot操作,迁移slot,传入的参数为:quiet=>true,:dots=>false,:update=>true。
11、迁移完成后更新sn[dst_idx]和sn[src_idx]的balance值。如果balance值为0后,游标向前进1。
12、直到dst_idx到达src_idx游标,完成整个rebalance操作。
add-node命令可以将新节点加入集群,节点可以为master,也可以为某个master节点的slave。
add-node new_host:new_port existing_host:existing_port
–cluster-slave
–cluster-master-id
add-node有两个可选参数:
参数 | 说明 |
---|---|
new_host:new_port existing_host:existing_port | new_host:new_port 新节点的ip:port;existing_host:existing_port,要加入集群的一个master的ip:port, |
–cluster-slave | 设置该参数,则新节点以slave的角色加入集群 |
–cluster-master-id | 新加入的节点要放到哪个master下。这个参数需要设置了–cluster-slave才能生效,如果不设置该参数,则会随机为新节点选择一个master节点。 |
可以看下add-node命令的执行示例:
[root@cache01 redis]# redis-cli --cluster add-node 192.168.75.187:7007 192.168.75.187:7003 --cluster-slave --cluster-master-id d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
>>> Adding node 192.168.75.187:7007 to cluster 192.168.75.187:7003
>>> Performing Cluster Check (using node 192.168.75.187:7003)
M: c276f98fb8f6b74cccceb3eb7399702fa6644cd9 192.168.75.187:7003
slots:[0-4],[5461-5466],[10923-16383] (5472 slots) master
1 additional replica(s)
M: d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143 192.168.75.187:7002
slots:[5467-10922] (5456 slots) master
1 additional replica(s)
S: e59bc95e8fadbcc1acaf95ada1621b8594c48007 192.168.75.187:7006
slots: (0 slots) slave
replicates d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
S: ac47bd2d21c50500cc59c0f35720801f49e8cbba 192.168.75.187:7005
slots: (0 slots) slave
replicates 97901b9d1281fb8b27b26898340ec1682dfffdba
S: 3605efaeea1afcfd373f17181cf09a02915aa098 192.168.75.187:7004
slots: (0 slots) slave
replicates c276f98fb8f6b74cccceb3eb7399702fa6644cd9
M: 97901b9d1281fb8b27b26898340ec1682dfffdba 192.168.75.187:7001
slots:[5-5460] (5456 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
add-node流程如下:
1、通过load_cluster_info_from_node方法转载集群信息,check_cluster方法检查集群是否健康。
2、如果设置了–slave,则需要为该节点寻找master节点。设置了–master-id,则以该节点作为新节点的master,如果没有设置–master-id,则调用get_master_with_least_replicas方法,寻找slave数量最少的master节点。如果slave数量一致,则选取load_cluster_info_from_node顺序发现的第一个节点。load_cluster_info_from_node顺序的第一个节点是add-node设置的existing_host:existing_port节点,后面的顺序根据在该节点执行cluster nodes返回的结果返回的节点顺序。
3、连接新的节点并与集群第一个节点握手。
4、如果没设置–slave就直接返回ok,设置了–slave,则需要等待确认新节点加入集群,然后执行cluster replicate命令复制master节点。
5、至此,完成了全部的增加节点的流程。
del-node可以把某个节点从集群中删除。del-node只能删除没有分配slot的节点。删除命令传递两个参数:
del-node host:port node_id
host:port:从该节点获取集群信息。
node_id:需要删除的节点id。
del-node执行结果示例如下:
[root@cache01 redis]# redis-cli --cluster del-node 192.168.75.187:7001 d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143
>>> Removing node d3316138a3d30dbaeceda65fc6fb8a2eeaeb2143 from cluster 192.168.75.187:7001
del-node流程如下:
1、通过load_cluster_info_from_node方法转载集群信息。
2、根据传入的node id获取节点,如果节点没找到,则直接提示错误并退出。
3、如果节点分配的slot不为空,则直接提示错误并退出。
4、遍历集群内的其他节点,执行cluster forget命令,从每个节点中去除该节点。如果删除的节点是master,而且它有slave的话,这些slave会去复制其他master,调用的方法是get_master_with_least_replicas,与add-node没设置–master-id寻找master的方法一样。
5、然后关闭该节点。