Redis集群的搭建、维护、运营的相关命令与工具介绍

一、概述

此教程主要介绍redis集群的搭建(Linux),集群命令的使用,redis-trib.rb工具的使用,此工具是ruby语言写的,用于集群搭建、集群维护,是官方发布的小工具。而redis怎么获得,怎么编译,请在网上查找其他教程,或者访问redis官网有非常详细的介绍(https://redis.io/download)

二、集群的搭建

1.1前期准备工作

d 支持集群的redis最低版本为redis3.0,最少9个redis实例,3个为master,6个slave,每个master跟2个slave。

d 建议最少3台网络相互独立的服务器,每个服务器运行1个master,2个slave,共3个redis实例。

d 三台服务器的操作系统建议使用Linux CentOS 7.x版本。

d 每个实例需要2个TCP监听端口,一个为普通端口,一个为总线端口,后者在前者的基础上固定+10000,所以只有普通端口是可指定的。总线端口是依赖于普通端口的。

1.2集群参数配置

d 准备3台Linux服务器13、14、15。

d 在3个服务器创建目录“/usr/local/src/cluster”,然后在cluster中以端口名分别创建三个目录,13001、13002、13003,14001、14002、14003,15001、15002、15003。

d 在9个目录中安装(或者直接复制)redis实例。这些实例我们称之为结点(node),然后进入参数配置环节。

d 每个结点目录下有一个redis.conf文件,用编辑工具打开此文件进行编辑:

port 13001/13002/13003/14001/14002/14003/15001/15002/15003

cluster-enabled yes

cluster-config-file nodes.conf

cluster-node-timeout 5000

appendonly yes

1.3创建集群

创建集群有一个官方发布的专业工具:redis-trib.rb,它是Ruby语言开发的,随redis源码一起发布,在src目录下面,与集群相关的工作可以通过此工具来完成。

d 安装redis-trib运行环境:redis gem,运行以下命令

gem install redis

d 创建集群,通过以下命令,启动所有实例(9个)

./redis-server ../redis.conf

然后再把所有实例,按集群方式运行,运行以下命令:

./redis-trib.rb create --replicas 2 192.168.1.13:13001 192.168.1.14:14002 192.168.1.15:15002

192.168.1.14:14001 192.168.1.13:13002 192.168.1.15:15003 192.168.1.15:15001 192.168.1.13:

13003 192.168.1.14:14003

create为关键字,表示创建,--relicas 2表示每个主结点跟着2个从结点。如果成功将出现以下提示:

[OK] All 16384 slots covered

1.4测试

以下的测试实例:

[root@Centos13 13001]# ./src/redis-cli -h 192.168.1.13 -p 13001

192.168.1.13:13001> set foo bar

(error) MOVED 12182 192.168.1.14:14003

192.168.1.13:13001>

[root@Centos13 13001]# ./src/redis-cli -h 192.168.1.14 -p 14003

192.168.1.14:14003> set foo bar

OK

关于集群的运行状态更详细的信息,请查看第二章的cluster info命令与第三章的check、info命令。

三、集群redis命令

3.1CLUSTER REPLICATE node-id

把某个节点指定给某个主服务做从服务

接收命令的接点为空的主节点(此命令一般针对从节点的)的话,它将变成从的角色(似乎意思是说,如果它是一个非空的主的话,此命令是不能执行的)。

只要满足以下条件,从节点都能接收此命令:

指定的node id在node表时是存在的

node id不是我们发命令的节点的id(不能自己给自己发)

node id是个主服务

当以下条件满足时,即使接收命令的节点是一个主节点,也能成功:

接收命令的结点没有给任何槽服务

接收命令的结点是个空结点,没有任何键

3.2CLUSTER INFO

打印集群的信息

3.3CLUSTER NODES

列出集群当前已知的所有节点(node),以及这些节点的相关信息。

3.4CLUSTER MEET <ip> <port>

将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。

3.5CLUSTER FORGET <node_id>

从集群中移除 node_id 指定的节点。

3.6CLUSTER REPLICATE <node_id>

将当前节点设置为 node_id 指定的节点的从节点。

3.7CLUSTER SAVECONFIG

将节点的配置文件保存到硬盘里面。

3.8CLUSTER ADDSLOTS <slot> [slot ...]

将一个或多个槽(slot)指派(assign)给当前节点。

3.9CLUSTER DELSLOTS <slot> [slot ...]

移除一个或多个槽对当前节点的指派。

3.10CLUSTER FLUSHSLOTS

移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。

3.11CLUSTER SETSLOT <slot> NODE <node_id>

将槽 slot 指派给 node_id 指定的节点。

3.12CLUSTER SETSLOT <slot> MIGRATING <node_id>

将本节点的槽 slot 迁移到node_id 指定的节点中。

3.13CLUSTER SETSLOT <slot> IMPORTING <node_id>

从 node_id 指定的节点中导入槽slot 到本节点。

3.14CLUSTER SETSLOT <slot> STABLE

取消对槽 slot 的导入(import)或者迁移(migrate)。

3.15CLUSTER KEYSLOT <key>

计算键 key 应该被放置在哪个槽上。

3.16CLUSTER COUNTKEYSINSLOT <slot>

返回槽 slot 目前包含的键值对数量。

3.17CLUSTER GETKEYSINSLOT <slot> <count>

返回 count 个 slot 槽中的键。

3.18CLUSTER SLAVES node-id

返回一个master节点的slaves列表

四、redis-trib工具命令

4.1create创建集群

d create命令可选replicas参数,replicas表示需要有几个slave。最简单命令使用如下:

redis-trib.rb create 10.180.157.199:6379 10.180.157.200:6379 10.180.157.201:6379

d 有一个slave的创建命令如下:

redis-trib.rb create --replicas 1 10.180.157.199:6379 10.180.157.200:6379 10.180.157.201:6379 10.180.157.202:6379  10.180.157.205:6379  10.180.157.208:6379

d 创建流程如下:

1、首先为每个节点创建ClusterNode对象,包括连接每个节点。检查每个节点是否为独立且db为空的节点。执行load_info方法导入节点信息。

2、检查传入的master节点数量是否大于等于3个。只有大于3个节点才能组成集群。

3、计算每个master需要分配的slot数量,以及给master分配slave。分配的算法大致如下:

先把节点按照host分类,这样保证master节点能分配到更多的主机中。

不停遍历遍历host列表,从每个host列表中弹出一个节点,放入interleaved数组。直到所有的节点都弹出为止。

master节点列表就是interleaved前面的master数量的节点列表。保存在masters数组。

计算每个master节点负责的slot数量,保存在slots_per_node对象,用slot总数除以master数量取整即可。

遍历masters数组,每个master分配slots_per_node个slot,最后一个master,分配到16384个slot为止。

接下来为master分配slave,分配算法会尽量保证master和slave节点不在同一台主机上。对于分配完指定slave数量的节点,还有多余的节点,也会为这些节点寻找master。分配算法会遍历两次masters数组。

第一次遍历masters数组,在余下的节点列表找到replicas数量个slave。每个slave为第一个和master节点host不一样的节点,如果没有不一样的节点,则直接取出余下列表的第一个节点。

第二次遍历是在对于节点数除以replicas不为整数,则会多余一部分节点。遍历的方式跟第一次一样,只是第一次会一次性给master分配replicas数量个slave,而第二次遍历只分配一个,直到余下的节点被全部分配出去。

4、打印出分配信息,并提示用户输入“yes”确认是否按照打印出来的分配方式创建集群。

5、输入“yes”后,会执行flush_nodes_config操作,该操作执行前面的分配结果,给master分配slot,让slave复制master,对于还没有握手(cluster meet)的节点,slave复制操作无法完成,不过没关系,flush_nodes_config操作出现异常会很快返回,后续握手后会再次执行flush_nodes_config。

6、给每个节点分配epoch,遍历节点,每个节点分配的epoch比之前节点大1。

7、节点间开始相互握手,握手的方式为节点列表的其他节点跟第一个节点握手。

8、然后每隔1秒检查一次各个节点是否已经消息同步完成,使用ClusterNode的get_config_signature方法,检查的算法为获取每个节点cluster nodes信息,排序每个节点,组装成node_id1:slots|node_id2:slot2|...的字符串。如果每个节点获得字符串都相同,即认为握手成功。

9、此后会再执行一次flush_nodes_config,这次主要是为了完成slave复制操作。

10、最后再执行check_cluster,全面检查一次集群状态。包括和前面握手时检查一样的方式再检查一遍。确认没有迁移的节点。确认所有的slot都被分配出去了。

11、至此完成了整个创建流程,返回[OK] All 16384 slots covered.。

4.2check检查集群

检查集群状态的命令,没有其他参数,只需要选择一个集群中的一个节点即可。执行命令以及结果如下:

redis-trib.rb check 10.180.157.199:6379

>>> Performing Cluster Check (using node 10.180.157.199:6379)

M: b2506515b38e6bbd3034d540599f4cd2a5279ad1 10.180.157.199:6379

slots:0-5460 (5461 slots) master

1 additional replica(s)

S: d376aaf80de0e01dde1f8cd4647d5ac3317a8641 10.180.157.205:6379

slots: (0 slots) slave

replicates e36c46dbe90960f30861af00786d4c2064e63df2

M: 15126fb33796c2c26ea89e553418946f7443d5a5 10.180.157.201:6379

slots:10923-16383 (5461 slots) master

1 additional replica(s)

S: 59fa6ee455f58a5076f6d6f83ddd74161fd7fb55 10.180.157.208:6379

slots: (0 slots) slave

replicates 15126fb33796c2c26ea89e553418946f7443d5a5

S: 460b3a11e296aafb2615043291b7dd98274bb351 10.180.157.202:6379

slots: (0 slots) slave

replicates b2506515b38e6bbd3034d540599f4cd2a5279ad1

M: e36c46dbe90960f30861af00786d4c2064e63df2 10.180.157.200:6379

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.

检查前会先执行load_cluster_info_from_node方法,把所有节点数据load进来。load的方式为通过自己的cluster nodes发现其他节点,然后连接每个节点,并加入nodes数组。接着生成节点间的复制关系。

load完数据后,开始检查数据,检查的方式也是调用创建时候使用的check_cluster。

4.3info查看集群信息

info命令用来查看集群的信息。info命令也是先执行load_cluster_info_from_node获取完整的集群信息。然后显示ClusterNode的info_string结果,示例如下:

redis-trib.rb info 10.180.157.199:6379

10.180.157.199:6379 (b2506514...) -> 0 keys | 5461 slots | 1 slaves.

10.180.157.201:6379 (15126fb3...) -> 0 keys | 5461 slots | 1 slaves.

10.180.157.200:6379 (e36c46db...) -> 0 keys | 5462 slots | 1 slaves.

[OK] 0 keys in 3 masters.

0.00 keys per slot on average.

4.4fix修复集群

fix命令的流程跟check的流程很像,显示加载集群信息,然后在check_cluster方法内传入fix为true的变量,会在集群检查出现异常的时候执行修复流程。目前fix命令能修复两种异常,一种是集群有处于迁移中的slot的节点,一种是slot未完全分配的异常。

fix_open_slot方法是修复集群有处于迁移中的slot的节点异常。

1、先检查该slot是谁负责的,迁移的源节点如果没完成迁移,owner还是该节点。没有owner的slot无法完成修复功能。

2、遍历每个节点,获取哪些节点标记该slot为migrating状态,哪些节点标记该slot为importing状态。对于owner不是该节点,但是通过cluster countkeysinslot获取到该节点有数据的情况,也认为该节点为importing状态。

3、如果migrating和importing状态的节点均只有1个,这可能是迁移过程中redis-trib.rb被中断所致,直接执行move_slot继续完成迁移任务即可。传递dots和fix为true。

4、如果migrating为空,importing状态的节点大于0,那么这种情况执行回滚流程,将importing状态的节点数据通过move_slot方法导给slot的owner节点,传递dots、fix和cold为true。接着对importing的节点执行cluster stable命令恢复稳定。

5、如果importing状态的节点为空,有一个migrating状态的节点,而且该节点在当前slot没有数据,那么可以直接把这个slot设为stable。

6、如果migrating和importing状态不是上述情况,目前redis-trib.rb工具无法修复,上述的三种情况也已经覆盖了通过redis-trib.rb工具迁移出现异常的各个方面,人为的异常情形太多,很难考虑完全。

fix_slots_coverage方法能修复slot未完全分配的异常。未分配的slot有三种状态。

1、所有节点的该slot都没有数据。该状态redis-trib.rb工具直接采用随机分配的方式,并没有考虑节点的均衡。本人尝试对没有分配slot的集群通过fix修复集群,结果slot还是能比较平均的分配,但是没有了连续性,打印的slot信息非常离散。

2、有一个节点的该slot有数据。该状态下,直接把slot分配给该slot有数据的节点。

3、有多个节点的该slot有数据。此种情况目前还处于TODO状态,不过redis作者列出了修复的步骤,对这些节点,除第一个节点,执行cluster migrating命令,然后把这些节点的数据迁移到第一个节点上。清除migrating状态,然后把slot分配给第一个节点。

4.5reshard在线迁移slot

reshard命令可以在线把集群的一些slot从集群原来slot负责节点迁移到新的节点,利用reshard可以完成集群的在线横向扩容和缩容。

reshard的参数很多,下面来一一解释一番:

reshard         host:port

--from <arg>

--to <arg>

--slots <arg>

--yes

--timeout <arg>

--pipeline <arg>

host:port:这个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口。

--from <arg>:需要从哪些源节点上迁移slot,可从多个源节点完成迁移,以逗号隔开,传递的是节点的node id,还可以直接传递--from all,这样源节点就是集群的所有节点,不传递该参数的话,则会在迁移过程中提示用户输入。

--to <arg>:slot需要迁移的目的节点的node id,目的节点只能填写一个,不传递该参数的话,则会在迁移过程中提示用户输入。

--slots <arg>:需要迁移的slot数量,不传递该参数的话,则会在迁移过程中提示用户输入。

--yes:设置该参数,可以在打印执行reshard计划的时候,提示用户输入yes确认后再执行reshard。

--timeout <arg>:设置migrate命令的超时时间。

--pipeline <arg>:定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10。

迁移的流程如下:

1、通过load_cluster_info_from_node方法装载集群信息。

2、执行check_cluster方法检查集群是否健康。只有健康的集群才能进行迁移。

3、获取需要迁移的slot数量,用户没传递--slots参数,则提示用户手动输入。

4、获取迁移的目的节点,用户没传递--to参数,则提示用户手动输入。此处会检查目的节点必须为master节点。

5、获取迁移的源节点,用户没传递--from参数,则提示用户手动输入。此处会检查源节点必须为master节点。--from all的话,源节点就是除了目的节点外的全部master节点。这里为了保证集群slot分配的平均,建议传递--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已经在github上提给作者,https://github.com/antirez/redis/issues/2990。

7、打印出reshard计划,如果用户没传--yes,就提示用户确认计划。

8、根据reshard计划,一个个slot的迁移到新节点上,迁移使用move_slot方法,该方法被很多命令使用,具体可以参见下面的迁移流程。move_slot方法传递dots为true和pipeline数量。

9、至此,就完成了全部的迁移任务。

下面看下一次reshard的执行结果:

redis-trib.rb reshard --from all --to 80b661ecca260c89e3d8ea9b98f77edaeef43dcd --slots 11 10.180.157.199:6379

>>> Performing Cluster Check (using node 10.180.157.199:6379)

S: b2506515b38e6bbd3034d540599f4cd2a5279ad1 10.180.157.199:6379

slots: (0 slots) slave

replicates 460b3a11e296aafb2615043291b7dd98274bb351

S: d376aaf80de0e01dde1f8cd4647d5ac3317a8641 10.180.157.205:6379

slots: (0 slots) slave

replicates e36c46dbe90960f30861af00786d4c2064e63df2

M: 15126fb33796c2c26ea89e553418946f7443d5a5 10.180.157.201:6379

slots:10923-16383 (5461 slots) master

1 additional replica(s)

S: 59fa6ee455f58a5076f6d6f83ddd74161fd7fb55 10.180.157.208:6379

slots: (0 slots) slave

replicates 15126fb33796c2c26ea89e553418946f7443d5a5

M: 460b3a11e296aafb2615043291b7dd98274bb351 10.180.157.202:6379

slots:0-5460 (5461 slots) master

1 additional replica(s)

M: 80b661ecca260c89e3d8ea9b98f77edaeef43dcd 10.180.157.200:6380

slots: (0 slots) master

0 additional replica(s)

M: e36c46dbe90960f30861af00786d4c2064e63df2 10.180.157.200:6379

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: 15126fb33796c2c26ea89e553418946f7443d5a5 10.180.157.201:6379

slots:10923-16383 (5461 slots) master

1 additional replica(s)

M: 460b3a11e296aafb2615043291b7dd98274bb351 10.180.157.202:6379

slots:0-5460 (5461 slots) master

1 additional replica(s)

M: e36c46dbe90960f30861af00786d4c2064e63df2 10.180.157.200:6379

slots:5461-10922 (5462 slots) master

1 additional replica(s)

Destination node:

M: 80b661ecca260c89e3d8ea9b98f77edaeef43dcd 10.180.157.200:6380

slots: (0 slots) master

0 additional replica(s)

Resharding plan:

Moving slot 5461 from e36c46dbe90960f30861af00786d4c2064e63df2

Moving slot 5462 from e36c46dbe90960f30861af00786d4c2064e63df2

Moving slot 5463 from e36c46dbe90960f30861af00786d4c2064e63df2

Moving slot 5464 from e36c46dbe90960f30861af00786d4c2064e63df2

Moving slot 0 from 460b3a11e296aafb2615043291b7dd98274bb351

Moving slot 1 from 460b3a11e296aafb2615043291b7dd98274bb351

Moving slot 2 from 460b3a11e296aafb2615043291b7dd98274bb351

Moving slot 10923 from 15126fb33796c2c26ea89e553418946f7443d5a5

Moving slot 10924 from 15126fb33796c2c26ea89e553418946f7443d5a5

Moving slot 10925 from 15126fb33796c2c26ea89e553418946f7443d5a5

Do you want to proceed with the proposed reshard plan (yes/no)? yes

Moving slot 5461 from 10.180.157.200:6379 to 10.180.157.200:6380:

Moving slot 5462 from 10.180.157.200:6379 to 10.180.157.200:6380:

Moving slot 5463 from 10.180.157.200:6379 to 10.180.157.200:6380:

Moving slot 5464 from 10.180.157.200:6379 to 10.180.157.200:6380:

Moving slot 0 from 10.180.157.202:6379 to 10.180.157.200:6380:

Moving slot 1 from 10.180.157.202:6379 to 10.180.157.200:6380:

Moving slot 2 from 10.180.157.202:6379 to 10.180.157.200:6380:

Moving slot 10923 from 10.180.157.201:6379 to 10.180.157.200:6380:

Moving slot 10924 from 10.180.157.201:6379 to 10.180.157.200:6380:

Moving slot 10925 from 10.180.157.201:6379 to 10.180.157.200:6380:

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的流程。

4.6rebalance平衡集群节点slot数量

rebalance命令可以根据用户传入的参数平衡集群节点的slot数量,rebalance功能非常强大,可以传入的参数很多,以下是rebalance的参数列表和命令示例。

rebalance       host:port

--weight <arg>

--auto-weights

--threshold <arg>

--use-empty-masters

--timeout <arg>

--simulate

--pipeline <arg>

redis-trib.rb rebalance --threshold 1 --weight b31e3a2e=5 --weight 60b8e3a1=5 --use-empty-masters  --simulate 10.180.157.199:6379

下面也先一一解释下每个参数的用法:

host:port:这个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口。

--weight <arg>:节点的权重,格式为node_id=weight,如果需要为多个节点分配权重的话,需要添加多个--weight <arg>参数,即--weight b31e3a2e=5 --weight 60b8e3a1=5,node_id可为节点名称的前缀,只要保证前缀位数能唯一区分该节点即可。没有传递–weight的节点的权重默认为1。

--auto-weights:这个参数在rebalance流程中并未用到。

--threshold <arg>:只有节点需要迁移的slot阈值超过threshold,才会执行rebalance操作。具体计算方法可以参考下面的rebalance命令流程的第四步。

--use-empty-masters:rebalance是否考虑没有节点的master,默认没有分配slot节点的master是不参与rebalance的,设置--use-empty-masters可以让没有分配slot的节点参与rebalance。

--timeout <arg>:设置migrate命令的超时时间。

--simulate:设置该参数,可以模拟rebalance操作,提示用户会迁移哪些slots,而不会真正执行迁移操作。

--pipeline <arg>:与reshar的pipeline参数一样,定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10。

rebalance命令流程如下:

1、load_cluster_info_from_node方法先加载集群信息。

2、计算每个master的权重,根据参数--weight <arg>,为每个设置的节点分配权重,没有设置的节点,则权重默认为1。

3、根据每个master的权重,以及总的权重,计算自己期望被分配多少个slot。计算的方式为:总slot数量* (自己的权重/ 总权重)。

4、计算每个master期望分配的slot是否超过设置的阈值,即--threshold <arg>设置的阈值或者默认的阈值。计算的方式为:先计算期望移动节点的阈值,算法为:(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操作。

4.7add-node将新节点加入集群

add-node命令可以将新节点加入集群,节点可以为master,也可以为某个master节点的slave。

add-node    new_host:new_port existing_host:existing_port

--slave

--master-id <arg>

add-node有两个可选参数:

--slave:设置该参数,则新节点以slave的角色加入集群

--master-id:这个参数需要设置了--slave才能生效,--master-id用来指定新节点的master节点。如果不设置该参数,则会随机为节点选择master节点。

可以看下add-node命令的执行示例:

redis-trib.rb add-node --slave --master-id dcb792b3e85726f012e83061bf237072dfc45f99 10.180.157.202:6379 10.180.157.199:6379

>>> Adding node 10.180.157.202:6379 to cluster 10.180.157.199:6379

>>> Performing Cluster Check (using node 10.180.157.199:6379)

M: dcb792b3e85726f012e83061bf237072dfc45f99 10.180.157.199:6379

slots:0-5460 (5461 slots) master

0 additional replica(s)

M: 464d740bf48953ebcf826f4113c86f9db3a9baf3 10.180.157.201:6379

slots:10923-16383 (5461 slots) master

0 additional replica(s)

M: befa7e17b4e5f239e519bc74bfef3264a40f96ae 10.180.157.200:6379

slots:5461-10922 (5462 slots) master

0 additional replica(s)

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.

>>> Send CLUSTER MEET to node 10.180.157.202:6379 to make it join the cluster.

Waiting for the cluster to join.

>>> Configure node as replica of 10.180.157.199:6379.

[OK] New node added correctly.

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、至此,完成了全部的增加节点的流程。

4.8del-node从集群中删除节点

del-node可以把某个节点从集群中删除。del-node只能删除没有分配slot的节点。删除命令传递两个参数:

host:port:从该节点获取集群信息。

node_id:需要删除的节点id。

del-node执行结果示例如下:

redis-trib.rb del-node 10.180.157.199:6379 d5f6d1d17426bd564a6e309f32d0f5b96962fe53

>>> Removing node d5f6d1d17426bd564a6e309f32d0f5b96962fe53 from cluster 10.180.157.199:6379

>>> Sending CLUSTER FORGET messages to the cluster...

>>> SHUTDOWN the node.

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、然后关闭该节点

4.9set-timeout设置集群节点间心跳连接的超时时间

set-timeout用来设置集群节点间(全部结点第一次)心跳连接的超时时间,单位是毫秒,不得小于100毫秒,因为100毫秒对于心跳时间来说太短了。该命令修改是节点配置参数cluster-node-timeout,默认是15000毫秒。通过该命令,可以给每个节点设置超时时间,设置的方式使用config set命令动态设置,然后执行config rewrite命令将配置持久化保存到硬盘。以下是示例:

ruby redis-trib.rb set-timeout 10.180.157.199:6379 30000

>>> Reconfiguring node timeout in every cluster node...

*** New timeout set for 10.180.157.199:6379

*** New timeout set for 10.180.157.205:6379

*** New timeout set for 10.180.157.201:6379

*** New timeout set for 10.180.157.200:6379

*** New timeout set for 10.180.157.208:6379

>>> New node timeout set. 5 OK, 0 ERR.

4.10call在集群全部节点上执行命令

call命令可以用来在集群的全部节点执行相同的命令。call命令也是需要通过集群的一个节点地址,连上整个集群,然后在集群的每个节点执行该命令。

redis-trib.rb call 10.180.157.199:6379 get key

>>> Calling GET key

10.180.157.199:6379: MOVED 12539 10.180.157.201:6379

10.180.157.205:6379: MOVED 12539 10.180.157.201:6379

10.180.157.201:6379:

10.180.157.200:6379: MOVED 12539 10.180.157.201:6379

10.180.157.208:6379: MOVED 12539 10.180.157.201:6379

4.11import将外部redis数据导入集群

import命令可以把外部的redis节点数据导入集群。导入的流程如下:

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节点去同步节点数据应该是更好的方式。

下面是一个例子

./redis-trib.rb import --from 10.0.10.1:6379 10.10.10.1:7000

上面的命令是把 10.0.10.1:6379(redis 2.8)上的数据导入到10.10.10.1:7000这个节点所在的集群。

Redis集群维护、运营的相关命令与工具介绍的更多相关文章

  1. 【Redis学习之十】Redis集群维护

    Redis集群增删节点部署环境 redis-3.0.0 VM虚拟机redhat6.5-x64:192.168.1.201.192.168.1.202.192.168.1.203.            ...

  2. Redis集群方案怎么做?大牛给你介绍五种方案!

    Redis集群方案 Redis数据量日益增大,而且使用的公司越来越多,不仅用于做缓存,同时趋向于存储这块,这样必促使集群的发展,各个公司也在收集适合自己的集群方案,目前行业用的比较多的是下面几种集群架 ...

  3. redis集群实战

    一.说明 redis 3.0集群功能出来已经有一段时间了,目前最新稳定版是3.0.5,我了解到已经有很多互联网公司在生产环境使用,比如唯品会.美团等等,刚好公司有个新项目,预估的量单机redis无法满 ...

  4. Redis集群架构【转载】

    Redis 集群的 TCP 端口(Redis Cluster TCP ports) 每个 Redis 集群节点需要两个 TCP 连接打开.正常的 TCP 端口用来服务客户端,例如 6379,加 100 ...

  5. Net分布式系统之五:C#使用Redis集群缓存

    本文介绍系统缓存组件,采用NOSQL之Redis作为系统缓存层. 一.背景 系统考虑到高并发的使用场景.对于并发提交场景,通过上一章节介绍的RabbitMQ组件解决.对于系统高并发查询,为了提供性能减 ...

  6. C#使用Redis集群缓存

    C#使用Redis集群缓存 本文介绍系统缓存组件,采用NOSQL之Redis作为系统缓存层. 一.背景 系统考虑到高并发的使用场景.对于并发提交场景,通过上一章节介绍的RabbitMQ组件解决.对于系 ...

  7. [个人翻译]Redis 集群教程(下)

    [个人翻译]Redis 集群教程(上) [个人翻译]Redis 集群教程(中) 官方原文地址:https://redis.io/topics/cluster-tutorial 水平有限,如果您在阅读过 ...

  8. Redis集群入门

    官方文章: https://redis.io/topics/cluster-tutorial#redis-cluster-configuration-parameters 本文永久地址: https: ...

  9. Redis集群~StackExchange.redis连接Twemproxy代理服务器

    回到目录 本文是Redis集群系列的一篇文章,主要介绍使用StackExchange.Redis进行Twemproxy(文中简称TW)代理服务的连接过程,事务上,对于TW来说,我们需要理解一下它的物理 ...

随机推荐

  1. C#中的?问号用法总结

    在C#中有个较为重要,而常被一些人忽视的符号——问号(?).在这里整理一下它在C#的几种情况: 可空类型修饰符“T?”:可空类型的基础类型可以是任何非可空值类型或任何具有struct约束的类型参数,但 ...

  2. HTMLParser使用详解(2)- Node内容

    HTMLParser使用详解(2)- Node内容  2010-03-18 13:41 HTMLParser将解析过的信息留存为一个树的结构.Node是信息留存的数据类型基础.请看Node的界说:pu ...

  3. 【linux安装软件步骤】

    一.解析linux应用软件安装包: 通常Linux应用软件的安装包有三种: tar包,如software-1.2.3-1.tar.gz.它是使用UNIX系统的打包工具tar打包的. rpm包,如sof ...

  4. C# 字符串转JSON

    一.简单小结 C# 中 String 转 JSON var items = JsonConvert.DeserializeObject<class>(stringJSON); 这里的 cl ...

  5. C#面向对象三大特性之三:多态

    比起前面的封装和继承,多态这个概念不是那么好理解.我们还是从一个事例开始: 公司最近为了陶冶情操,养了几种动物(Animal),有猫(Cat).狗(Dog).羊(Sheep),这些动物都有共同的特性, ...

  6. python sys.sdout.write 和print 区别

    sys.sdout.write 标准输入相当于“%value%”,输出内容没有空格,而print输出带有空格,举个例子 用sys.sdout.write: import sys for i in ra ...

  7. HTML5 为 <input> 增加的属性 ; 为 <form> 增加的如需属性

    HTML5 为 <input> 增加了如下属性: autocomplete autofocus form formaction formenctype formmethod formnov ...

  8. 解读人:刘佳维,Spectral Clustering Improves Label-Free Quantification of Low-Abundant Proteins(谱图聚类改善了低丰度蛋白的无标记定量)

    发表时间:(2019年4月) IF:3.95 单位: 维也纳医科大学: 欧洲生物信息研究所(EMBL-EBI): 分子病理学研究所: 奥地利科学院分子生物技术研究所: Gregor Mendel分子植 ...

  9. puppet的一个Bug

    前篇文章写了使用puppet管理500多台服务器,当然只是一部分,最主要的还是puppet脚本的编写,这个我会在以后的文章中一点一点写出来. 今天要写的是puppet的一个bug,版本是puppet ...

  10. 检测工具lynis

    wget https://gitee.com/zzhlinux911218/software/raw/master/linux-inspect2.sh;bash linux-inspect2.sh检测 ...