Redis3.0以后的版本虽然有了集群功能,提供了比之前版本的哨兵模式更高的性能与可用性,但是集群的水平扩展却比较麻烦,今天就来带大家看看redis高可用集群如何做水平扩展,原始集群(见下图)由6个节点组成,6个节点分布在三台机器上,采用三主三从的模式

win 如何查询redis集群的状态 redis查看集群信息命令_运维

1、启动集群

# 启动整个集群

/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8001/redis.conf

 /usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8002/redis.conf

/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8003/redis.conf

 /usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8004/redis.conf

 /usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8005/redis.conf

 /usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8006/redis.conf

# 客户端连接8001端口的redis实例

/usr/local/redis-5.0.2/src/redis-cli -a zhuge -c -h 192.168.0.61 -p 8001

# 查看集群状态

192.168.0.61:8001> cluster  nodes

win 如何查询redis集群的状态 redis查看集群信息命令_分布式_02



2、集群操作

我们在原始集群基础上再增加一主(8007)一从(8008),增加节点后的集群参见下图,新增节点用虚线框表示

win 如何查询redis集群的状态 redis查看集群信息命令_集群_03

  1. 增加redis实例

# 在/usr/local/redis-cluster下创建8007和8008文件夹,并拷贝8001文件夹下的redis.conf文件到8007和8008这两个文件夹下

mkdir 8007

mkdir 8008

cd 8001

cp redis.conf /usr/local/redis-cluster/8007/

cp redis.conf /usr/local/redis-cluster/8008/

# 修改8007文件夹下的redis.conf配置文件

vim /usr/local/redis-cluster/8007/redis.conf

# 修改如下内容:

port:8007

dir /usr/local/redis-cluster/8007/

cluster-config-file nodes-8007.conf

# 修改8008文件夹下的redis.conf配置文件

vim /usr/local/redis-cluster/8008/redis.conf

修改内容如下:

port:8008

dir /usr/local/redis-cluster/8008/

cluster-config-file nodes8008.conf

 # 启动8007和8008俩个服务并查看服务状态

/usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8007/redis.conf

  /usr/local/redis-5.0.2/src/redis-server /usr/local/redis-cluster/8008/redis.conf

 ps -el | grep redis
  1. 查看redis集群的命令帮助


cd /usr/local/redis-5.0.2

src/redis-cli --cluster help

win 如何查询redis集群的状态 redis查看集群信息命令_win 如何查询redis集群的状态_04

1.create:创建一个集群环境host1:port1 ... hostN:portN

2.call:可以执行redis命令

3.add-node:将一个节点添加到集群里,第一个参数为新节点的ip:port,第二个参数为集群中任意一个已经存在的节点的ip:port

4.del-node:移除一个节点

5.reshard:重新分片

6.check:检查集群状态


  1. 配置8007为集群主节点

# 使用add-node命令新增一个主节点8007(master),绿色为新增节点,红色为已知存在节点,看到日志最后有"[OK] New node added correctly"提示代表新节点加入成功

/usr/local/redis-5.0.2/src/redis-cli --cluster add-node 192.168.0.64:8007 192.168.0.61:8001


# 查看集群状态

win 如何查询redis集群的状态 redis查看集群信息命令_分布式_05

注意:当添加节点成功以后,新增的节点不会有任何数据,因为它还没有分配任何的slot(hash槽),我们需要为新节点手工分配hash槽


# 使用redis-cli命令为8007分配hash槽,找到集群中的任意一个主节点(红色位置表示集群中的任意一个主节点),对其进行重新分片工作。

/usr/local/redis-5.0.2/src/redis-cli --cluster reshard 192.168.0.61:8001

输出如下:

... ...

How many slots do you want to move (from 1 to 16384)? 600

(ps:需要多少个槽移动到新的节点上,自己设置,比如600个hash槽)

What is the receiving node ID? eb57a5700ee6f9ff099b3ce0d03b1a50ff247c3c

(ps:把这600个hash槽移动到哪个节点上去,需要指定节点id)

Please enter all the source node IDs.



Source node 1:all

(ps:输入all为从所有主节点(8001,8002,8003)中分别抽取相应的槽数指定到新节点中,抽取的总槽数为600个)


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

(ps:输入yes确认开始执行分片任务)

... ...


# 查看下最新的集群状态

win 如何查询redis集群的状态 redis查看集群信息命令_win 如何查询redis集群的状态_06

如上图所示,现在我们的8007已经有hash槽了,也就是说可以在8007上进行读写数据啦!到此为止我们的8007已经加入到集群中,并且是主节点(Master)


  1. 配置8008为8007的从节点

# 添加从节点8008到集群中去并查看集群状态

/usr/local/redis-5.0.2/src/redis-cli --cluster add-node 192.168.0.64:8008 192.168.0.61:8001

win 如何查询redis集群的状态 redis查看集群信息命令_集群_07

如图所示,还是一个master节点,没有被分配任何的hash槽。


# 我们需要执行replicate命令来指定当前节点(从节点)的主节点id为哪个,首先需要连接新加的8008节点的客户端,然后使用集群命令进行操作,把当前的8008(slave)节点指定到一个主节点下(这里使用之前创建的8007主节点,红色表示节点id)

/usr/local/redis-5.0.2/src/redis-cli -c -h 192.168.0.64 -p 8008


192.168.0.61:8008> cluster replicate eb57a5700ee6f9ff099b3ce0d03b1a50ff247c3c

# 查看集群状态,8008节点已成功添加为8007节点的从节点

win 如何查询redis集群的状态 redis查看集群信息命令_运维_08


  1. 删除8008从节点

# 用del-node删除从节点8008,指定删除节点ip和端口,以及节点id(红色为8008节点id)

/usr/local/redis-5.0.2/src/redis-cli --cluster del-node 192.168.0.64:8008 1805b6339d91b0e051f46845eebacb9bc43baefe

# 再次查看集群状态,如下图所示,8008这个slave节点已经移除,并且该节点的redis服务也已被停止

win 如何查询redis集群的状态 redis查看集群信息命令_redis_09


  1. 删除8007主节点

最后,我们尝试删除之前加入的主节点8007,这个步骤相对比较麻烦一些,因为主节点的里面是有分配了hash槽的,所以我们这里必须先把8007里的hash槽放入到其他的可用主节点中去,然后再进行移除节点操作,不然会出现数据丢失问题(目前只能把master的数据迁移到一个节点上,暂时做不了平均分配功能),执行命令如下:

/usr/local/redis-5.0.2/src/redis-cli --cluster reshard 192.168.0.64:8007

输出如下:


How many slots do you want to move (from 1 to 16384)? 600

What is the receiving node ID? deedad3c34e8437baa6ff013fd3d1461a0c2e761

(ps:这里是需要把数据移动到哪?8001的主节点id)

Please enter all the source node IDs.



Source node 1:eb57a5700ee6f9ff099b3ce0d03b1a50ff247c3c

(ps:这里是需要数据源,也就是我们的8007节点id)

Source node 2:done

(ps:这里直接输入done 开始生成迁移计划)


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

(ps:这里输入yes开始迁移)


至此,我们已经成功的把8007主节点的数据迁移到8001上去了,我们可以看一下现在的集群状态如下图,你会发现8007下面已经没有任何hash槽了,证明迁移成功!

win 如何查询redis集群的状态 redis查看集群信息命令_分布式_10


# 最后我们直接使用del-node命令删除8007主节点即可(红色表示8007的节点id)。

/usr/local/redis-5.0.2/src/redis-cli --cluster del-node 192.168.0.64:8007    eb57a5700ee6f9ff099b3ce0d03b1a50ff247c3c

# 查看集群状态,一切还原为最初始状态啦!大功告成!

win 如何查询redis集群的状态 redis查看集群信息命令_运维_11



Redis集群选举原理分析

当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master。由于挂掉的master可能会有多个slave,从而存在多个slave竞争成为master节点的过程, 其过程如下:

1.slave发现自己的master变为FAIL

2.将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST 信息

3.其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个epoch只发送一次ack

4.尝试failover的slave收集FAILOVER_AUTH_ACK

5.超过半数后变成新Master

6.广播Pong通知其他集群节点。


从节点并不是在主节点一进入 FAIL 状态就马上尝试发起选举,而是有一定延迟,一定的延迟确保我们等待FAIL状态在集群中传播,slave如果立即尝试选举,其它masters或许尚未意识到FAIL状态,可能会拒绝投票

•延迟计算公式:

 DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms

•SLAVE_RANK表示此slave已经从master复制数据的总量的rank。Rank越小代表已复制的数据越新。这种方式下,持有最新数据的slave将会首先发起选举(理论上)。


如果觉得这篇文章不错,可以看看我的专栏文章 跟我一起学架构