环境
- redis 6.0.8
docker pull redis:6.0.8
- 宿主机
- window (主力 - 挂在data目录时主从容错切换失败,没有进行切换) 去你妈的,用centos把
- vmare - centos 7(本来是windows上错误时才用)
- docker desktop
- Docker version 20.10.11, build dea9396
- docker-compose version 1.29.2, build 5becea4c
- 自定义配置文件
- 官方配置文件
- bind 0.0.0.0(Linux and windows)
- cluster-announce-ip 192.168.0.65 (windows 宿主机IP)
启动redis
挂载的目录
- windows(垃圾系统)
-v /D/docker/redis-share/redis-node-{num}/data:/data-v /D/docker/redis-share/redis-node-{num}/redis.conf:/etc/redis/redis.conf
- linux
-v /tn/redis-share/redis-node-{num}/data:/data-v /tn/redis-share/redis-node-{num}/redis.conf:/etc/redis/redis.conf
- 命令分步解释
docker run : 创建并运行docker容器实例--name redis-node-6 : 容器名字--net host : 使用宿主机的IP和端口,默认(windows mac上无效,老实使用 -p 6001:6001 -p 16001:16001 )--privileged=true : 获取宿主机root用户权限-v /D/docker/redis-share/redis-node-1:/data : 容器卷,宿主机地址:docker内部地址redis:6.0.8 : redis镜像和版本号--cluster-enabled yes : 开启redis集群--appendonly yes : 开启持久化--port 6386 : redis端口号
- 节点 一 ~ 六
- Redis集群中的各个节点,需要开放一个端口,同其他节点建立连接,用于接收心跳数据等操作。也就是说,redis-node1节点,开放6379端口供client连接时,同时提供16379端口(10000 + 6379),供其他Redis节点连接。
- springBoot连接失败,因为内部重定向到了172这个docker的内网IP
- 通过–net host,指定网络类型为host,使得容器与宿主机使用同一网络,从而规避了这类问题
- window不行
- Redis集群中的各个节点,需要开放一个端口,同其他节点建立连接,用于接收心跳数据等操作。也就是说,redis-node1节点,开放6379端口供client连接时,同时提供16379端口(10000 + 6379),供其他Redis节点连接。
# 我 centos# docker rm -f redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5 redis-node-6docker run -d --name redis-node-1 --net host --privileged=true -v /tn/redis-share/redis-node-1/data:/data -v /tn/redis-share/redis-node-1/redis.conf:/etc/redis/redis.conf redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6001docker run -d --name redis-node-2 --net host --privileged=true -v /tn/redis-share/redis-node-2/data:/data -v /tn/redis-share/redis-node-2/redis.conf:/etc/redis/redis.conf redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6002docker run -d --name redis-node-3 --net host --privileged=true -v /tn/redis-share/redis-node-3/data:/data -v /tn/redis-share/redis-node-3/redis.conf:/etc/redis/redis.conf redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6003docker run -d --name redis-node-4 --net host --privileged=true -v /tn/redis-share/redis-node-4/data:/data -v /tn/redis-share/redis-node-4/redis.conf:/etc/redis/redis.conf redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6004docker run -d --name redis-node-5 --net host --privileged=true -v /tn/redis-share/redis-node-5/data:/data -v /tn/redis-share/redis-node-5/redis.conf:/etc/redis/redis.conf redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6005docker run -d --name redis-node-6 --net host --privileged=true -v /tn/redis-share/redis-node-6/data:/data -v /tn/redis-share/redis-node-6/redis.conf:/etc/redis/redis.conf redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6006# windows## -v /D/docker/redis-share/redis-node-1:/data 挂载磁盘会导致主从切换失败## --network host windows无法使用这个,会导致外部无法连接docker run -d --name redis-node-1 -p 6001:6001 -p 16001:16001 -v /D/docker/redis-share/redis-node-1/redis.conf:/etc/redis/redis.conf --privileged=true redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6001docker run -d --name redis-node-2 -p 6002:6002 -p 16002:16002 -v /D/docker/redis-share/redis-node-2/redis.conf:/etc/redis/redis.conf --privileged=true redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6002docker run -d --name redis-node-3 -p 6003:6003 -p 16003:16003 -v /D/docker/redis-share/redis-node-3/redis.conf:/etc/redis/redis.conf --privileged=true redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6003docker run -d --name redis-node-4 -p 6004:6004 -p 16004:16004 -v /D/docker/redis-share/redis-node-4/redis.conf:/etc/redis/redis.conf --privileged=true redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6004docker run -d --name redis-node-5 -p 6005:6005 -p 16005:16005 -v /D/docker/redis-share/redis-node-5/redis.conf:/etc/redis/redis.conf --privileged=true redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6005docker run -d --name redis-node-6 -p 6006:6006 -p 16006:16006 -v /D/docker/redis-share/redis-node-6/redis.conf:/etc/redis/redis.conf --privileged=true redis:6.0.8 redis-server /etc/redis/redis.conf --cluster-enabled yes --appendonly yes --port 6006
构建集群关系 (3主3从)
运行命令
--cluster-replicas 1表示为每个master创建一个slave节点
# 进入node1容器内docker exec -it redis-node-1 bash# 构建集群关系 (注意,进入docker容器后才能执行一下命令,且注意自己的真实IP地址 )# --net host(windows不能用这个 -p -p 可以使用)redis-cli --cluster create 192.168.0.65:6001 192.168.0.65:6002 192.168.0.65:6003 192.168.0.65:6004 192.168.0.65:6005 192.168.0.65:6006 --cluster-replicas 1# --net host(windows不能用这个) windows okredis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1# my windows# 可以使用 172.17.0.2~7 ( ` docker network inspect bridge ` 查看), 也可以直接使用docker的IP(windos ` ipconfig ` 以太网适配器 vEthernet (WSL))redis-cli --cluster create 172.28.224.1:6001 172.28.224.1:6002 172.28.224.1:6003 172.28.224.1:6004 172.28.224.1:6005 172.28.224.1:6006 --cluster-replicas 1# my centosredis-cli --cluster create 192.168.126.138:6001 192.168.126.138:6002 192.168.126.138:6003 192.168.126.138:6004 192.168.126.138:6005 192.168.126.138:6006 --cluster-replicas 1
进入redis
redis-cli -p 6001 (因为指定了redis启动的端口,所以cli必须指定端口:1-6)
查看集群状态
# 集群信息cluster info# 集群 节点 - 状态cluster nodes# 检查集群redis-cli --cluster check 127.0.0.1:6002
- 随机 master - slave 对应

数据存储
不能单机连接(会出现存储失败),需要加入参数
-c以集群环境连接redis-cli -p 6001 -c
- (error) MOVED 12706 127.0.0.1:6003 ······

主从容错切换迁移
测试内容:master挂了,slave是否会启动 (当前测试 6001挂了,他的小弟6006会不会启动。<以实际情况为准>)
- stop 6001
docker stop redis-node-1 - 去其他节点查看 节点状态
docker exec -it redis-node-2 bashredis-cli -p 6002 -ccluster nodes
Windows出现没有切换成功
查看slave节点日志
# 启动1:S 25 Jan 2022 08:31:54.693 * MASTER <-> REPLICA sync started1:S 25 Jan 2022 08:31:54.693 * Non blocking connect for SYNC fired the event.1:S 25 Jan 2022 08:31:54.693 * Master replied to PING, replication can continue...1:S 25 Jan 2022 08:31:54.693 * Partial resynchronization not possible (no cached master)1:S 25 Jan 2022 08:31:54.694 * Full resync from master: b9c9d2d98e62a2b2d248aa070e73f4ecc622f7dc:01:S 25 Jan 2022 08:31:54.804 * MASTER <-> REPLICA sync: receiving 175 bytes from master to disk1:S 25 Jan 2022 08:31:54.805 * MASTER <-> REPLICA sync: Flushing old data1:S 25 Jan 2022 08:31:54.805 * MASTER <-> REPLICA sync: Loading DB in memory1:S 25 Jan 2022 08:31:54.807 # Failed trying to load the MASTER synchronization DB from disk# 选举 6.0.81:S 25 Jan 2022 08:26:50.300 * MASTER <-> REPLICA sync started1:S 25 Jan 2022 08:26:50.300 # Error condition on socket for SYNC: Operation now in progress# 选举 6.2.61:S 25 Jan 2022 08:54:51.141 # Error condition on socket for SYNC: Connection refused1:S 25 Jan 2022 08:54:52.144 * Connecting to MASTER 127.0.0.1:6002
- 怀疑是window的在进程中不允许对文件操作的问题照成的
- 我把挂载的磁盘去掉用在挂载,就切换成功了
Linux(Centos )切换成功

连接问题
springboot 连接时出现了问题
Unable to connect to [172.17.0.3:6002]: connection timed out: /172.17.0.3:6002
出现环境 windows上的springboot程序,连接vm中docker下的redis集群
- 这个的出现时由于没有使用 —net host 这个参数,而是指定的两个 -p
-p clientPord:clientPord -p heartPort:heartPort导致容器默认使用了桥接网络模式(bridge)让 redis重定向的地址端为172.17.0.~,这个地址在宿主机是访问不了- ```shell 127.0.0.1:6001> cluster nodes e1a99d912ff0d9d25e5bde0d8a24beabd04e8ba6 172.17.0.7:6006@16006 master - 0 1643164452000 7 connected 10923-16383 aa040b7ca76f3621fa2444d25609340c766fd5b1 172.17.0.5:6004@16004 slave 2bc26cccd52d47ebc69842ca32c3ce7fefcd3cd0 0 1643164453920 1 connected cce2bbb92fecee8c52e26ac85304ab65979d1022 172.17.0.3:6002@16002 master - 0 1643164452000 2 connected 5461-10922 7b3bae5775c9c2b545d01cfa4e06c85006c3a016 172.17.0.4:6003@16003 master,fail - 1643164436842 1643164433829 3 connected 2bc26cccd52d47ebc69842ca32c3ce7fefcd3cd0 172.17.0.2:6001@16001 myself,master - 0 1643164452000 1 connected 0-5460 79e6c887d21a0d9665064f7375e83fc8510d2f6a 172.17.0.6:6005@16005 slave cce2bbb92fecee8c52e26ac85304ab65979d1022 0 16431644
- 这个的出现时由于没有使用 —net host 这个参数,而是指定的两个 -p
C:\Users\tnnn>ping 172.17.0.3
正在 Ping 172.17.0.3 具有 32 字节的数据: 请求超时。
172.17.0.3 的 Ping 统计信息: 数据包: 已发送 = 1,已接收 = 0,丢失 = 1 (100% 丢失), Control-C
- [通过配置路由表实现ip互通 ](https://www.cnblogs.com/brock0624/p/9788710.html) 我没有配置成功- 查看路由表 `route print`- 查看dockerIP `ipconfig` 太网适配器 vEthernet (WSL)- 添加路由 route -p add 172.17.0.0 MASK 255.255.255.0 xxx- 通过配置文件固定IP处理成功- cluster-announce-ip 192.168.0.65 (宿主机IP)- `/D/docker/redis-share/redis-node-6/redis.conf:/etc/redis/redis.conf redis:6.0.8 redis-server /etc/redis/redis.conf`- 连接失败- 将redis.cnf 中的 bind 改成 bind 0.0.0.0 (这个我不确定,但是下面的防火墙是真的问题)- centos防火墙默认开启了的- firewal状态(防火墙)```shellfirewall-cmd --statesystemctl status firewalld // 查看防火墙状态
停止firewal(防火墙)
systemctl stop firewalld.service
禁止firewall开机启动(防火墙)
systemctl disable firewalld.service
重启firewall(防火墙)
springboot 连接
maven
<!--redis start --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--redis end -->
application.yml
- 6001 6002 6003为初始的master节点,如果后面主从切换了之后,6001 6002 6003 不在时master了可以不出现错误
- cluster.nodes 中必须要保证有一个节点不会挂,要不然就连不到了(3主三从 的情况像几乎不会这种情况)
- 在节点关闭时,节点还没连接信息还是正常的会出现报错
spring:redis:database: 0timeout: 10000 # 连接超时(毫秒)jedis:pool:max-active: 100 # 最大连接数(负值则无限制)max-idle: 100 # 最大空闲连接max-wait: -1 # 最大阻塞等待时间(负值则无限制)min-idle: 50 # 最小空闲连接cluster:max-redirects: 12 # 重定向的最大数量,比如第一台挂了,连第二台,第二台挂了连第三台,这个重新连接的最大数量nodes:# windows docker redis集群测试连接地址- 192.168.0.65:6001- 192.168.0.65:6002- 192.168.0.65:6003# centos docker redis集群测试连接地址- 192.168.126.138:6001- 192.168.126.138:6002- 192.168.126.138:6003
测试
import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.redis.core.StringRedisTemplate;@SpringBootTestclass SpringbootRedisShareApplicationTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testvoid contextLoads() {stringRedisTemplate.opsForValue().set("das","dasdd");}}
