cluster 集群架构图
通过hash分配数据分片到不同的redis主机。在应用端配置redis cluster地址时需要将所有节点的ip和端口都添加上。
使用cluster集群创建的key,在哪个节点上创建的只能是自身节点可以查到数据,其他节点看不到。
redis cluster不合理的架构图
不太合理的架构图
cluster集群每个机器上都有多个master和slave,如果master节点的数据备份都在自己主机的slave上,那么当服务器1坏掉后,这个机器上的数据就丢失了,数据丢失整个应用就崩溃了。
合理的架构图
每个节点slave都存放在别的主机,即使当前主机挂掉,另一台直接还原数据即可。
部署一个cluster三主三从集群具体步骤
- 在三台主机上部署redis,分别启动两个不同端口的redis,一个主库一个从库
- 配置cluster集群自动发现,使得集群中各个主机都知道其他主机上的redis节点
- 配置集群hash分配槽位,有了槽位才可以存储数据
- 使用cluster replicate使多出来的三个主库变成从库,这样就实现了三主三从
环境准备
更多关于 Redis 学习的文章,请参阅:NoSQL 数据库系列之 Redis ,本系列持续更新中。
部署redis cluster节点
搭建一个三主三从的redis cluster集群。配置文件中的bind也可以写成如下样子,自动识别bind地址。
bind $(ifconfig | awk 'NR==2{print $2}')
配置文件含义
port 6380 //redis端口
daemonize yes //后台启动
logfile /data/redis_cluster/redis_6380/logs/redis_6380.log //日志路径
pidfile /data/redis_cluster/redis_6380/pid/redis_6380.log //pid存放路径
dbfilename "redis_6380.rdb" //数据文件名称
dir /data/redis_cluster/redis_6380/data //数据文件存放目录
cluster-enabled yes //开启集群模式
cluster-config-file node_6380.conf //集群数据文件路径,保存集群信息的文件
cluster-node-timeout 15000 //集群故障转移时间,多长时间无响应就切
redis-1配置
配置文件自动识别bind地址
#创建节点配置文件路径
[root@redis-1 ~]# mkdir -p /data/redis_cluster/redis_{6380,6381}/{conf,data,logs,pid}
#准备两个配置文件一个6380,一个6381
[root@redis-1 ~]# cat > /data/redis_cluster/redis_6380/conf/redis_6380.conf CLUSTER MEET 192.168.81.230 6381
OK
#查看配置文件是否增加,所有节点的配置文件都会生成
[root@redis-1 ~]# cat /data/redis_cluster/redis_6381/data/node_6381.conf
759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612169812886 4 connected
1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 myself,master - 0 0 1 connected
87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 master - 0 1612169814797 2 connected
bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 master - 0 1612169815806 0 connected
a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 master - 0 1612169815708 5 connected
b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 master - 0 1612169816814 3 connected
vars currentEpoch 5 lastVoteEpoch 0
cluster集群分配操作
redis cluster通讯流程
集群内消息传递是同步的
在分布式存储中需要提供维护节点元数据信息的机制,所谓元数据是指:节点负责哪些数据,是否出现故障灯状态信息,redis集群采用gossip协议,gossip协议工作原理就是节点彼此不断交换信息,一段时间后所有的节点偶会指定集群完整信息,这种方式类似于流言传播,因此只需要在一台节点配置集群信息所有节点都能收到信息
通信过程:
- 1.集群中的每一个节点都会单独开辟一个tcp通道用于节点之间彼此通信,通信端口在基础端口上增加10000
- 2.每个节点在固定周期内通过特定规则选择结构节点发送ping消息
- 3.接收到ping消息的节点用pong作为消息响应,集群中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点的信息,也可能知道部分节点信息,只要这些节点彼此可以正常通信,最终他们就会达成一致的状态,当节点出现故障,新节点加入,主从角色变化等,彼此之间不断发生ping/pong消息,最终达成同步的模板
通讯消息类型:gossip,信息交换,常见的消息分为ping、pong、meet、fail。
通讯示意图 没有分配槽位时集群的状态,所有节点执行cluster info,cluster_state都是fail,fail状态表示集群不可用,没有分配槽位,cluster_slots都会显示0。
手动配置集群槽位
每个cluster集群都有16384个槽位,我们有三台机器,想要手动分配平均就需要使用16384除3。
redis-1 0-5461
redis-2 5462-10922
redis-3 10923-16383
分配槽位语法格式(交互式):CLUSTER ADDSLOTS 0 5461
。
分配槽位语法:redis-cli -h 192.168.81.210 -p 6380 cluster addslots {0…5461}
。
删除槽位分配语法格式:redis-cli -h 192.168.81.210 -p 6380 cluster delslots {5463…10921}
。
#配置手动分配槽位
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster addslots {0..5461}
OK
[root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380 cluster addslots {5462..10922}
OK
[root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6380 cluster addslots {10923..16383}
OK
#查看集群状态,到目前为止集群已经是可用的了
[root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5
cluster_my_epoch:2
cluster_stats_messages_sent:170143
cluster_stats_messages_received:170142
#查看nodes文件内容
[root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380 cluster nodes
a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 master - 0 1612251539412 5 connected
bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 master - 0 1612251538402 0 connected
87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 myself,master - 0 0 2 connected 5462-10922
b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 master - 0 1612251540418 3 connected 0-5461
1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 master - 0 1612251537394 1 connected
759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612251536386 4 connected 10923-16383
更多关于 Redis 学习的文章,请参阅:NoSQL 数据库系列之 Redis ,本系列持续更新中。
创建key验证集群是否可用
不是所有的key都能插入,有的key插入的时候就提示说你应该去192.168.81.230上插入,这时手动到对应的主机上执行就可以插入,这是由于cluster集群槽位都是分布在不同节点的,每次新建一个key,都会通过hash算法均匀的在不同节点去创建
不同节点创建的key只由自己节点可以看到自己创建的数据
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380
192.168.81.210:6380> set k1 v1
(error) MOVED 12706 192.168.81.230:6380
192.168.81.210:6380> set k2 v2
OK
192.168.81.210:6380> set k3 v3
OK
192.168.81.210:6380> set k4 v4
(error) MOVED 8455 192.168.81.220:6380
192.168.81.210:6380> set k5 v5
(error) MOVED 12582 192.168.81.230:6380
192.168.81.210:6380> set k6 v6
OK
[root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6380
192.168.81.230:6380> set k1 v1
OK
192.168.81.230:6380> set k5 v5
OK
[root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380
192.168.81.220:6380> set k4 v4
OK
ASK路由解决key创建提示去别的主机创建
可以通过ASK路由解决创建key时提示去别的主机进行创建。
ASK路由创建key时,如果可以在本机直接创建就会执行创建key的命令,如果不能再本机执行,他会根据提示的主机去对应主机上创建key。
ASK路径的特性:每次通过hash在指定主机上创建了key后就会停留在这个主机上。
只需要执行redis-cli时加上-c参数即可。
[root@redis-1 ~]# redis-cli -c -h 192.168.81.210 -p 6380
192.168.81.210:6380> set k8 v8
-> Redirected to slot [8331] located at 192.168.81.220:6380
OK
192.168.81.220:6380> set k9 v9
-> Redirected to slot [12458] located at 192.168.81.230:6380
OK
192.168.81.230:6380> set k10 v10
OK
192.168.81.230:6380> set k11 v11
OK
192.168.81.230:6380> set k12 v12
-> Redirected to slot [2863] located at 192.168.81.210:6380
OK
192.168.81.210:6380> set k13 v13
-> Redirected to slot [6926] located at 192.168.81.220:6380
OK
192.168.81.220:6380> set k14 v14
-> Redirected to slot [11241] located at 192.168.81.230:6380
OK
#很清楚的展示了在哪台主机上创建
验证hash分配是否均已
cluster架构是分布式的,创建的key会通过hash将数据均已的分布在每台主机的槽位上。
#插入一千条数据,查看三个节点是否分配均已
插入的时候使用-c,自动在某个节点上插入数据
[root@redis-1 ~]# for i in {1..1000}
do
redis-cli -c -h 192.168.81.210 -p 6380 set key_${i} value_${i}
done
#查看每个节点的数据量,可以看到非常均匀,误差只有一点点
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380
192.168.81.210:6380> DBSIZE
(integer) 339
[root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6380
192.168.81.220:6380> DBSIZE
(integer) 339
[root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6380
192.168.81.230:6380> DBSIZE
(integer) 336
192.168.81.230:6380> exit
配置cluster集群三主三从高可用
实现步骤
- 使用cluster replicate将主机的6381redis节点交叉成为别的主机6380节点的从库
- 查看集群状态即可
三主三从架构图
三主三从是redis cluster最常用的架构,每个从节点复制的都不是本机主库的数据,而是其他节点主库的数据,这样即使某一台主机坏掉了,从节点备份还是在其他机器上,这样就做到了高可用,三主三从架构允许最多坏一台主机。
三主三从我们采用交叉复制架构类型,这样可以做到最多坏一台主机集群还是正常可以用的,如果每台主机的6381节点都是6380节点的备份,那么这台机器坏了,集群就不可用了,因此想要做到高可用,就采用交叉复制。
交叉复制的架构,当主节点挂掉了,主节点备份的从节点就会自动成为主节点,当主节点上线后。
每个节点的6380端口都是主库,6381端口都是从库。
从节点对应的主节点关系
- redis-1的6381从节点对应的主节点是redis-2的6380主节点
- redis-2的6381从节点对应的主节点是redis-3的6380主节点
- redis-3的6381从节点对应的主节点是redis-1的6380主节点
将每一个节点都配置rdb持久化
在所有节点端口的配置文件中加上rdb持久化配置即可。
vim /data/redis_cluster/redis_6380/conf/redis_6380.conf
bind 192.168.81.210
port 6380
daemonize yes
logfile /data/redis_cluster/redis_6380/logs/redis_6380.log
pidfile /data/redis_cluster/redis_6380/pid/redis_6380.log
dbfilename "redis_6380.rdb"
dir /data/redis_cluster/redis_6380/data
cluster-enabled yes
cluster-config-file node_6380.conf
cluster-node-timeout 15000
#持久化配置
save 60 10000
save 300 10
save 900 1
重启redis
redis-cli -h 192.168.81.210 -p 6380 shutdown
redis-server /data/redis_cluster/redis_6380/conf/redis_6380.conf
配置三主三从
配置三主三从规范操作步骤
- 将集群信息粘到txt中,只保留下6380端口信息
- 配置命令在txt中准备好在复制到命令行
主节点我们已经有了,目前6个节点全是主节点,我们需要把所有主机的6381的主节点配置成从节点。
从节点对应的主节点关系:
- redis-1的6381从节点对应的主节点是redis-2的6380主节点
- redis-2的6381从节点对应的主节点是redis-3的6380主节点
- redis-3的6381从节点对应的主节点是redis-1的6380主节点
CLUSTER REPLICATE 是配置当前节点成为某个主节点的从节点,replicate命令其实就相当于执行了slaveof,同步了某一个主库,并且在日志中查看到的就是主从同步的过程
#配置从节点连接主节点,交叉式复制
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 CLUSTER REPLICATE 87ea6206f3db1dbaa49522bed15aed6f3bf16e22
OK
[root@redis-1 ~]# redis-cli -h 192.168.81.220 -p 6381 CLUSTER REPLICATE 759ad5659d449dc97066480e1b7efbc10b34461d
OK
[root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6381 CLUSTER REPLICATE b7748aedb5e51921db67c54e0c6263ed28043948
OK
#查看集群节点信息,发现已经是三主三从了
[root@redis-1 ~]# redis-cli -h 192.168.81.230 -p 6381 cluster nodes
a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 myself,slave b7748aedb5e51921db67c54e0c6263ed28043948 0 0 5 connected
bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 slave 759ad5659d449dc97066480e1b7efbc10b34461d 0 1612323918342 4 connected
b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 master - 0 1612323919350 3 connected 0-5461
1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 slave 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 0 1612323917331 2 connected
759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612323916826 4 connected 10923-16383
87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 master - 0 1612323920357 2 connected 5462-10922
配置完主从,可以看到集群中已经有slave节点了,并且也是交叉复制的。
打开主库的日志可以看到哪个从库同步了主库的日志,打开从库的日志可以看到同步了哪个主库的日志。更多关于 Redis 学习的文章,请参阅:NoSQL 数据库系列之 Redis ,本系列持续更新中。
模拟故障转移
三主三从架构允许最多坏一台主机,模拟将redis-1机器的主库6380挂掉,查看集群间的故障迁移
思路:
- 1.将redis-1的6380主库关掉,查看集群状态信息是否将slave自动切换为master
- 2.当master上线后会变成一个节点的从库
- 3.将master通过cluster failover重新成为主库
模拟坏掉redis-1的主库并验证就能是否可用
#挂掉redis-1的主库
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 shutdown
#查看日志
先是由于主库挂了状态变成fail,当从库变成主库后,状态再次变为ok
[root@redis-1 ~]# tail -f /data/redis_cluster/redis_6381/logs/redis_6381.log
124058:S 03 Feb 13:16:00.233 # Cluster state changed: fail
124058:S 03 Feb 13:17:01.857 # Cluster state changed: ok
#查看集群信息
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 cluster nodes
#查看集群状态
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:7
cluster_my_epoch:2
cluster_stats_messages_sent:18202
cluster_stats_messages_received:17036
#验证集群是否可用
[root@redis-1 ~]# redis-cli -c -h 192.168.81.210 -p 6381 set k1111 v1111
OK
当主库挂掉后,查看集群信息时会看到提示主库已经是fail状态,此时可用看到192.168.81.230机器的6381端口成为了master,192.168.81.230的6381端口是redis-1的从库,从库变为主库后,集群状态再次变为ok。
redis-1节点的主库恢复目前的架构图
当主库重新加入集群后,架构图就变成了如下样子,主库的6380就成为了192.168.81.230的从库,而192.168.81.230的从库变成了192.168.81.210的主库。
#启动redis-1的6380主库
[root@redis-1 ~]# redis-server /data/redis_cluster/redis_6380/conf/redis_6380.conf
#查看集群信息
[root@redis-1 ~]# redis-cli -c -h 192.168.81.210 -p 6380 cluster nodes
1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 slave 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 0 1612330250901 2 connected
b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 myself,slave a2c95db5d6f9f288e6768c8d00e90fb7631f3021 0 0 3 connected
759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612330255958 4 connected 10923-16383
bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 slave 759ad5659d449dc97066480e1b7efbc10b34461d 0 1612330252920 4 connected
a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 master - 0 1612330254941 7 connected 0-5461
87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 master - 0 1612330256960 2 connected 5462-10922
将恢的主库重新变为主库
目前主库已经重新上线了,且现在是192.168.81.230的从库,而原来192.168.81.230的从库变成了现在192.168.81.210的主库,我们需要把关系切换回来,不能让一台机器上同时存在两台主库,每次故障处理后一定要把架构修改会原来的样子。
从库切换成主库也特别简单,只需要执行一个cluster falover即可变为主库。
cluster falover确实也类似于关系互换,简单理解就是原来的从变成了主,现在的主变成了从,这样一来就可以把故障恢复的主机重新变为主库。
cluster falover原理:falover原理也就是先执行了slave no one,然后在对应的由主库变为从库的机器上执行了slave of。
#将故障上线的主库重新成为主库
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380
192.168.81.210:6380> CLUSTER FAILOVER
OK
#查看集群信息,192.168.81.210的发现6380重新成为了master,192.168.81.230的从库变成了slave
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6381 cluster nodes
759ad5659d449dc97066480e1b7efbc10b34461d 192.168.81.230:6380 master - 0 1612331847795 12 connected 10923-16383
87ea6206f3db1dbaa49522bed15aed6f3bf16e22 192.168.81.220:6380 master - 0 1612331849307 11 connected 5462-10922
b7748aedb5e51921db67c54e0c6263ed28043948 192.168.81.210:6380 master - 0 1612331848299 10 connected 0-5461
bedd9482b08a06b0678fba01bb1c24165e56636c 192.168.81.220:6381 slave 759ad5659d449dc97066480e1b7efbc10b34461d 0 1612331850317 12 connected
a2c95db5d6f9f288e6768c8d00e90fb7631f3021 192.168.81.230:6381 slave b7748aedb5e51921db67c54e0c6263ed28043948 0 1612331851324 10 connected
1ec79d498ecf9f272373740e402398e4c69cacb2 192.168.81.210:6381 myself,slave 87ea6206f3db1dbaa49522bed15aed6f3bf16e22 0 0 8 connected
查看集群信息,192.168.81.210的发现6380重新成为了master,192.168.81.230的从库变成了slave。到此cluster集群故障转移成功,集群状态一切正常。
[root@redis-1 ~]# redis-cli -h 192.168.81.210 -p 6380 cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:16
cluster_my_epoch:16
cluster_stats_messages_sent:18614
cluster_stats_messages_received:3497
更多关于 Redis 学习的文章,请参阅:NoSQL 数据库系列之 Redis ,本系列持续更新中。
需要注意的几点
生产环境数据量可能非常大,当主库故障重新上线时,执行CLUSTER FAILOVER会很慢,因为这个就相当于是主从复制切换了,从库(刚上线的原来主库)关闭主从复制,主库(主库坏掉前的从库)同步从库(刚上线的原来主库)数据,然后从库(刚上线的原来主库)重新变为主库,这个时间一定要等,切记,千万不要因为慢在主库上(主库坏掉前的从库)同步手动进行了CLUSTER REPLICATE,这样确实会非常快的将主库(主库坏掉前的从库)重新变为从库,但也意味着这个节点数据全部丢失,因为clusert replicate相当于slaveof,slaveof会把自己的库清掉,这时候从库(刚上线的原来主库)在执行这CLUSTER FAILOVER同步着主库(主库坏掉前的从库)的数据,主库那边执行了replicate去同步从库(刚上线的原来主库),从而导致从库(刚上线的原来主库)还没有同步完主库(主库坏掉前的从库的数据),主库(主库坏掉前的从库)数据就丢失,整个集群还是可以用的,只是这个主库节点和从节点数据全部丢失,其他两个主库从库还能使用。
切记,当从库执行CLUSTER FAILOVER变为主库时,一定不要在主库上执行CLUSTER REPLICATE变为从库,虽然CLUSTER REPLICATE变为从库很快,但是会清空自己的数据去同步主库,这时主库还没有数据,因此就会导致数据全部丢失。
CLUSTER FAILOVER:首先执行slave on one变为一个单独的节点,然后在要变成从库的节点上执行slaveof,只要从库执行完slave of,执行CLUSTER FAILOVER的节点就变成了主库。
CLUSTER REPLICATE:只是执行了slaveof使自身成为从节点。
当redis cluster主从正在同步时,不要执行cluster replicate,当主从复制完在执行,如何看主从是否复制完就要看节点的rdb文件是否是.tmp结尾的,如果是tmp结尾就说明他们正在同步数据,此时不要对集群做切换操作
总结
- 3.0版本以后推出集群功能
- cluster集群有16384个槽位,误差在2%之间
- 槽位与序号顺序无关,重点是槽的数量
- 通过发现集群,与集群之间实现消息传递
- 配置文件无需手动修改,都是自动生成的
- 分配操作,必须将所有的槽位分配完毕
- 理清复制关系,画图,按照图形执行复制命令
- 当集群状态为ok时,集群才可以正常使用
- 反复测试,批量插入key,验证分配是否均匀
- 测试高可用,关闭任意主节点,集群是否自动转移
- 当主节点修复后,执行主从关系切换
- 做实验尽量贴合生成环境,尽量使用和生成环境一样数量的数据
- 评估和记录同步数据、故障转移完成的时间
- 向领导汇报时要有图、文档、实验环境,随时都可以演示
当应用需要连接 redis cluster 集群时要将所有节点都写在配置文件中。
来源:https://jiangxl.blog.csdn.net/article/details/120879397