注意: 因为测试,我一个节点部署多个服务,生产环境建议分开不然会报 are on same IP,导致主从切换失败

1 使用场景

哨兵模式已经能够实现高可用,实践中通常是分布式服务,某一个点的分类数据放在指定的一个哨兵主从,通常也足够,但如果某个分类数据量实在过于庞大,哨兵+主从这种模式,相当于每个节点都是一个全量的数据副本,从高可扩方面来说,它这种模式不是很方便,对资源也是很大的浪费。当哨兵+主从遇到资源瓶颈,或者对高可扩有一定要求的时候,集群模式便能解决这个问题

  • 高可用原理

​ Redis 集群模式是没有中心节点的,它至少需要 3 个 master 节点,每个 master 节点至少一个 slave(默认读),也就是至少 6 个节点才能组建集群模式,已经内置了数据分片和故障转移。

​ 数据分片是 16384 个虚拟槽位分散到不同的 master 节点,设置 key 的时候,服务节点通过 key 的 hashcode % 16384,转发存放到不同的节点的对应分片槽位上。当查询请求到一个节点时,服务节点根据 key 检查槽位是否在当前节点,若存在则响应数据,若不存在则 moved 重定向到对应的服务节点。

​ 故障转移方面和哨兵类似,集群模式下各个节点之间通过 gossip 通信,相互 ping-pong,当一个节点对另外一个节点的心跳检查,超过 cluster_node_timeout 参数的值,则广播所有节点对其检查,当超过 50%的节点都认为此节点故障时则正式下线。若是从节点,断开时长超过 cluster_node_timeout * cluster-slave-validity-factor 这个组合参数值,则该从节点不再参与数据恢复。

​ 综合来看,集群模式在 5.0 后已经非常成熟,可以不用过多考虑扩容的问题,也减少了维护哨兵的工作。

img

2 环境信息

因为集群模式至少 3 个 master 节点,而每个主节点至少 1 个 slave,所以至少 6 个节点才能组建集群模式,下面以 6 个节点为例。

启动 6 个实例节点后,使用 redis-cli 建立初始集群关系,便建立自动维护关系的 Cluster 集群。

image-20220510111020845

3 部署 redis 集群

3.1 下载解压安装

wget http://download.redis.io/releases/redis-6.2.7.tar.gz

tar-zxvf redis-6.2.7.tar.gz

make

# make install # 这里我不安装值编译好直接运行

3.2 修改配置文件

此配置只当参考,不要在生产环境用,环境不同配置也不一样比如 repl-diskless-syn 设置同步方式为磁盘同步或者网络同步,磁盘慢网络带宽好的时候使用网络同步更好(详细配置参考: Redis配置详解)

参数名称 解释
daemonize yes redis 后台运行
appendonly yes aof 日志开启 有需要就开启,它会每次写操作都记录一条日志
bind 192.168.200.140 绑定 ip
cluster-config-file nodes_6379.conf 集群的配置 配置文件首次启动自动生成
cluster-enabled yes 开启集群 把注释#去掉
cluster-node-timeout 5000 请求超时 设置 5 秒够了,防止网络波动主从误切换
logfile “nodes_6379.log” 指定输出日志
masterauth passwd slave 节点数据同步 master 密码
pidfile /var/run/redis_6379.pid pidfile 文件对应端口号
port 6379 要开放端口
protected-mode no 禁止安全模式运行,主要拦截公网 ip 访问,如果开启会一直卡在获取
requirepass passwd 可选,配置 redis 密码,如果配置了一定要配置 masterauth,不然无法同步数据

3.3 启动 redis

src/redis-server 1114.conf

src/redis-server 1113.conf

redis4,加入集群

src/redis-cli --cluster create 192.168.1.133:6379 192.168.1.133:1110 192.168.1.133:1111 192.168.1.133:1112 192.168.1.133:1113 192.168.1.133:1114 --cluster-replicas 1 -a passwd

–replicas 1 代表一主一从, -a 是密码

关于主从节点的选择及槽的分配,其算法如下:

  1. 把节点按照 host 分类,这样保证 master 节点能分配到更多的主机中。
  2. 遍历 host 列表,从每个 host 列表中弹出一个节点,放入 interleaved 数组。直到所有的节点都弹出为止。
  3. 将 interleaved 数组中前 master 个数量的节点保存到 masters 数组中。
  4. 计算每个 master 节点负责的 slot 数量,16384 除以 master 数量取整,这里记为 N。
  5. 遍历 masters 数组,每个 master 分配 N 个 slot,最后一个 master,分配剩下的 slot。
  6. 接下来为 master 分配 slave,分配算法会尽量保证 master 和 slave 节点不在同一台主机上。对于分配完指定 slave 数量的节点,还有多余的节点,也会为这些节点寻找 master。分配算法会遍历两次 masters 数组。
  7. 第一次遍历 master 数组,在余下的节点列表找到 replicas 数量个 slave。每个 slave 为第一个和 master 节点 host 不一样的节点,如果没有不一样的节点,则直接取出余下列表的第一个节点。
  8. 第二次遍历是分配节点数除以 replicas 不为整数而多出的一部分节点。

执行指令后,提示预设的数据分片槽位信息 slots、主从关系信息等:

输入 yes

image-20211011162213380

创建完成

image-20211011162223437

三、检测

src/redis-cli -c -h 192.168.1.133 -p 1111 (-c 是进入集群模式)

CLUSTER nodes

(命令参考)

image-20211011162229514

存储的数据(key-value)是均匀分配到不同的节点的:

image-20211011162251295

以下文档新添加的,可能与上面环境不符,但是不影响观看

4 集群管理控制台

4.1 安装 redisinsight

docker run -d -v /data/redisinsight-data/:/db -p 8001:8001 redislabs/redisinsight:latest

4.2 登录添加集群

image-20220510112624172

选择所有节点

image-20220510113015440

4.3 查看集群状态

image-20220510113129353

5 节点下线维护

所有操作都可以在上面控制台实现

5.1 查看节点状态

src/redis-cli -c -h 10.1.1.1 -p 6379 -a passwd cluster nodes

5.2 master 节点,有两种方案(二选一)

5.2.1 直接移除哈希槽,然后下线

src/redis-cli –cluster reshard 10.1.1.1:6380 -a passwd

image-20220510113701245

5.2.2 改成 slave 节点

src/redis-cli -c -h 10.1.1.1(slave节点地址) -p 6380 -a passwd cluster failover

image-20220511114956461

5.3 移除节点

src/redis-cli --cluster del-node 10.1.1.3:6379 8285c1fbd2297aab9f031dafc0b9240b8fa89d15 -a passwd

5.4 查看集群状态

slave 自动同步 id 以 a41 的 master 节点

image-20220510113946610

image-20220510114549548

5.5 查看 slave 节点数据

image-20220510131149931

6 新加节点

6.1 添加节点

src/redis-cli –cluster add-node 10.1.1.3:6379(要加入的节点) 10.1.1.3:6380(当前集群已有节点) -a passwd

6.2 添加 master 节点

因为加进来默认就是 master 节点,直接分配哈希槽就行

src/redis-cli --cluster reshard 10.1.1.3:6379 -a passwd

6.2.1 写入测试

image-20220510125514125

6.3 添加 slave 节点

src/redis-cli --cluster add-node --cluster-slave --cluster-master-id 8e165e491c28a35488e4c6a2fa659ec41fe8053b(主节点的ID) 10.1.1.3:6380 (新加的从节点) 10.1.1.3:6379(主节点地址) -a passwd

6.3.1 查看数据同步

image-20220510130148845

7 高可用测试

7.1 停掉 slave

因为停掉 slave 不影响写入,所以不做写入测试,只测试能否自动加入集群

7.1.1 写入数据

image-20220510135130309

7.1.2 启动服务查看

启动后自动加入集群

image-20220510131053362

7.1.3 查看数据是否同步

8 会自动同步过来

image-20220510135211912

7.2 停掉 master

7.2.1 准备写入数据脚本

1
2
3
4
5
6
7
8
#!/bin/bash
NUM=2000
PASS=passwd
for i in `seq $NUM`;do
/opt/redis-6.2.7/src/redis-cli -c -h 10.1.1.1 -a "$PASS" --no-auth-warning set key${i} value${i}
echo "key${i} value${i} 写入完成"
done
echo "$NUM个key写入到Redis完成"

7.2.2 启动脚本,停止 master

slave 会自动变成 master

image-20220510131033137

7.2.3 写入数据,查看是否总共 2000 个 key

运行过程中发现脚本并不会检测这个节点能不能用. 服务不可用时间为:slave 检测 master 间隔+检测超时时间

降低不可用时间有两种方法:

  • 程序或者代理层做判断
  • 降低 slave 检测 master 超时时间与增加检测次数

image-20220510170912071

master 切换的节点数量与别的节点相比差了将近 500

image-20220510172355790

7.2.4 master 重新启动

会自动变成刚才 master 节点的 slave

image-20220510130956164

7.2.5 查看数据

只有 master 节点存在的 key 都会同步过来,唯一的问题是客户端不会自动禁止访问不可用的节点,中间需要加代理判断节点可不可用

image-20220510171108914

8 单节点数据迁移到集群

8.1 修改配置

如果 redis5.0 之前的版本,在移动槽点的时候,假如槽点内有值的话,导致报错:Syntax error ,try client(list|kill|getname|setname|pause|reply) ,主要就是需要修改 redis-trib.rb 文件的 move_slot 这个方法,绕过 clientCommand,直接执行 migrateCommand(去掉.client 即可)。

image-20211011163137793

8.2 修改哈希槽

把所有哈希槽放到一个节点上

1
src/redis-trib.rb reshard 192.168.1.114:6379

image-20211011163143128

8.3 迁移数据

关闭服务,把单节点的 rdb 文件改成这个节点的配置文件里面的名字

image-20211011163204031

8.4 恢复服务

启动服务

system start redis

重新分配哈希槽

1
src/redis-trib.rb reshard 192.168.1.114:6379

9 备份与还原

参考: Redis备份与恢复