上一篇文章讲解了Redis集群原理及搭建,由于工作中使用docker较多,本文主要讲解使用docker搭建集群及对集群的扩展收容。
环境:Centos7.6
Docker:20.10.12
Redis:6.2.6
集群配置步骤
1、创建redis-cluster.tmpl配置Redis信息【端口、是否开启集群等】
2、创建redis.sh配置需要创建的redis信息
3、添加网络,redis集群使用该网络
4、执行redis.sh实现创建redis
5、执行redis-cli创建集群
参考之前一篇文章《Docker安装及配置》
创建目录
mkdir -p /usr/local/server/redis-cluster cd /usr/local/server/redis-cluster vi redis-cluster.tmpl
创建 redis-cluster.tmpl
配置Redis信息(类似redis.conf):
#端口 port ${PORT} #非保护模式 protected-mode no #启用集群模式 cluster-enabled yes cluster-config-file nodes.conf #超时时间 cluster-node-timeout 5000 #集群各节点IP地址 cluster-announce-ip 192.168.88.110 #集群节点映射端口 cluster-announce-port ${PORT} #集群总线端口 cluster-announce-bus-port 1${PORT} #开启aof持久化策略 appendonly yes #后台运行 #daemonize yes #进程号存储 pidfile /var/run/redis_${PORT}.pid #集群加密 #masterauth 123456 #requirepass 123456
创建redis.sh
配置需要创建的 Redis 集群:
#!/bin/bash #在/usr/local/server/redis-cluster下生成conf和data目标,并生成配置信息 for port in `seq 7001 7006`; do mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf && mkdir -p ./${port}/data; done #创建6个redis容器 for port in `seq 7001 7006`; do docker run -d -it -p ${port}:${port} -p 1${port}:1${port} -v /usr/local/server/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /usr/local/server/redis-cluster/${port}/data:/data --privileged=true --restart always --name redis-${port} --net redis-net --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf; done #查找ip for port in `seq 7001 7006`; do echo -n "$(docker inspect --format '{{ (index .NetworkSettings.Networks "redis- net").IPAddress }}' "redis-${port}")":${port}" "; done #换行 echo -e "\n" #输入信息 read -p "请把输入要启动的docker容器名称,默认redis-7001:" DOCKER_NAME #判断是否为空 if [ ! $DOCKER_NAME ]; then DOCKER_NAME='redis-7001'; fi #进入容器 docker exec -it redis-7001 /bin/bash
创建 stop.sh
脚本,用于停止Redis容器,并且移除对应容器:
#!/bin/bash docker stop redis-7001 redis-7002 redis-7003 redis-7004 redis-7005 redis-7006 docker rm redis-7001 redis-7002 redis-7003 redis-7004 redis-7005 redis-7006 rm -rf 7001 7002 7003 7004 7005 7006
# 配置docker网络 docker network create redis-net # 脚本授权:给 和 添加可执行权限: chmod +x redis.sh chmod +x stop.sh
查看docker给每个节点分配的IP信息
docker network inspect redis-net | grep -i -E "name|ipv4address"
执行脚本开始安装Redis节点,并进入到 /usr/local/bin 目录下执行 redis-cli 创建集群关联:
执行启动./redis.sh
集群
关联集群
# 进入到任意一个安装好的redis节点的bin目录,里面有个脚本对象redis-cli, docker exec -it redis-7001 bash cd /usr/local/bin/ # 执行集群创建 ./redis-cli --cluster create 172.18.0.2:7001 172.18.0.3:7002 172.18.0.4:7003 172.18.0.5:7004 172.18.0.6:7005 172.18.0.7:7006 --cluster-replicas 1
redis-cli -p 7001 -c cluster nodes
其他查看集群信息命令
# 查看 主节点信息 redis-cli -p 7001 cluster nodes|grep master # 查看 从节点信息 redis-cli -p 7001 cluster nodes|grep slave # 查看集群信息 redis-cli --cluster info ip:端口 redis-cli --cluster check ip:端口
上面我们搭建了集群情况如下
目前共有6个节点,3对主从,其中7001分配了5416个哈希槽,7002分配了5462个哈希槽,7003分配了5461个哈希槽。随着业务增长,我们需要增加7007和7008 2台Redis,并添加到集群中。其中7007为主节点,7008为7007的从节点,并向主节点7001和7002获取2000个哈希槽。扩容后集群信息如下图:
基于Docker安装Redis这里编写了一个脚本,安装脚本 redis-port.sh 如下:
#!/bin/bash #在/usr/local/server/redis-cluster下生成conf和data目标,并生成配置信息 #换行 echo -e "\n" #输入信息 read -p "请输入容器端口:" DOCKER_PORT #输入端口赋值 port=$DOCKER_PORT; echo -e "$port" #创建配置文件 mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf && mkdir -p ./${port}/data; #创建redis容器 docker run -d -it -p ${port}:${port} -p 1${port}:1${port} -v /usr/local/server/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /usr/local/server/redis-cluster/${port}/data:/data --privileged=true --restart always --name redis-${port} --net redis-net --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf; #查找ip echo -n "启动$(docker inspect --format '{{ (index .NetworkSettings.Networks "redis- net").IPAddress }}' "redis-${port}")":${port}" 成功!"; echo -e "\n"
添加执行权限
chmod +x redis-port.sh
执行 redis-port.sh 脚本,实现 7007,7008节点安装。
我们需要给集群节点添加一个主节点,我们需要将 7007 节点添加到 7001 节点所在的集群中,并且添加后作为主节点,添加命令行如下:
# 将192.168.88.110:7007节点添加到192.168.88.110:7001节点所在的集群中 redis-cli --cluster add-node 192.168.88.110:7007 192.168.88.110:7001
此时我们可以进入到集群节点之一查看此时的集群状态,我们进入到7002节点中输入cluster node查询,操作方法如下
# 进入容器 docker exec -it redis-7002 /bin/bash # 进入到redis-cli脚本目录 cd /usr/local/bin # 登录7002节点 ./redis-cli -p 7002 -c # 查询集群状态 cluster nodes
哈希槽分配
从上面的集群节点信息我们可以看出一个问题,7007 节点没有分配哈希槽。因为之前3台Master已经瓜分了16384个哈希槽,所以再增加一个新节点是没有剩余哈希槽分配的,所以新增的 7007 节点没有分配到哈希槽。我们只能重新分配哈希槽,才能让新增节点分配到一定的哈希槽,重新分配哈希槽后,还要考虑之前其他Redis节点中的数据迁移。
重新分配Hash槽
我们将 7001,7002 中的 2000 个哈希槽挪给 7007 ,命令如下:
# 将7001集群中节点 # fbc63acf974997e37a35b5ca1c71cc002ae1bb40 # fa92c840b4a77463fb27b2b8183f144321a73f86 # 中的2000个哈希槽移动到 41eb57d0685f71aabef57908aef54189b22573b9中 redis-cli --cluster reshard 192.168.88.110:7001 --cluster-from fbc63acf974997e37a35b5ca1c71cc002ae1bb40,fa92c840b4a77463fb27b2b8183f144321a73f86 --cluster-to 41eb57d0685f71aabef57908aef54189b22573b9 --cluster-slots 2000
参数说明:
--cluster-from:表示slot目前所在的节点的node ID,多个ID用逗号分隔
--cluster-to:表示需要新分配节点的node ID
--cluster-slots:分配的slot数量
将2000个哈希槽挪给7007后,我们查询下节点信息:
redis-cli -p 7001 cluster nodes|grep master
我们需要往集群中给 7007 节点添加一个从节点 7008 ,添加从节点的主要目的是提高高可用,防止主节点宕机后该节点无法提供服务。添加从节点命令如下:
# 将192.168.88.110:7008节点添加到192.168.88.110:7007对应的集群中,并且加入的节点为从节点, # 对应的主节点 id是41eb57d0685f71aabef57908aef54189b22573b9 redis-cli --cluster add-node 192.168.88.110:7008 192.168.88.110:7007 --cluster-slave --cluster-master-id 41eb57d0685f71aabef57908aef54189b22573b9
参数说明:
add-node: 后面的分别跟着新加入的slave和slave对应的master
cluster-slave:表示加入的是slave节点
--cluster-master-id:表示slave对应的master的node ID
执行命令后,效果如下:
集群信息查看:
数据查看
到此集群热扩容已经完成,接下来对集群缩容操作。
在真实生产环境中,我们也会跟着我们的业务和环境执行缩容处理,比如双十一过后,流量没有那么大了,我们往往
会缩容处理,服务器开销。
Redis实现缩容,需要哈希槽重新分配,将需要移除的节点所分配的所有哈希槽值分配给其他需要运行工作的节点, 还需要移除该节点的从节点,然后再删除该节点。
移除 7007 的从节点 7008 ,命令如下:
# del-node:删除节点,后面跟着slave节点的 ip:port 和node ID redis-cli --cluster del-node 192.168.88.110:7008 7d6948bb8b6a5ff49f26aef2ebdb400bc3dc7062
我们需要将7007节点的哈希槽迁移到7001,7002,7003节点上,仍然用上面用过的redis-cli --cluster reshard ...
语法,迁移计划:500个slots给7001,700个slots给7002,剩余800个给7003 命令如下:
# 将192.168.88.110:7007节点所在集群中41eb57d0685f71aabef57908aef54189b22573b9 节点的500个哈希槽迁移给 # fbc63acf974997e37a35b5ca1c71cc002ae1bb40节点,不回显需要迁移的slot,直接迁移。 # 第一次迁移500到7001 redis-cli --cluster reshard 192.168.88.110:7007 --cluster-from 41eb57d0685f71aabef57908aef54189b22573b9 --cluster-to fbc63acf974997e37a35b5ca1c71cc002ae1bb40 --cluster-slots 500 --cluster-yes # 第二次迁移700到7002 redis-cli --cluster reshard 192.168.88.110:7007 --cluster-from 41eb57d0685f71aabef57908aef54189b22573b9 --cluster-to fa92c840b4a77463fb27b2b8183f144321a73f86 --cluster-slots 700 --cluster-yes # 第三次迁移800到7003 redis-cli --cluster reshard 192.168.88.110:7007 --cluster-from 41eb57d0685f71aabef57908aef54189b22573b9 --cluster-to 05e9c301a25041ca780f369974764636513e8767 --cluster-slots 800 --cluster-yes
查看集群状态
删除节点命令如下:
redis-cli --cluster del-node 192.168.88.110:7007 41eb57d0685f71aabef57908aef54189b22573b9
集群节点查看:
到此集群的缩容完成