环境

  • 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
  • 自定义配置文件

启动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
  1. 命令分步解释
    1. docker run : 创建并运行docker容器实例
    2. --name redis-node-6 : 容器名字
    3. --net host : 使用宿主机的IP和端口,默认(windows mac上无效,老实使用 -p 6001:6001 -p 16001:16001
    4. --privileged=true : 获取宿主机root用户权限
    5. -v /D/docker/redis-share/redis-node-1:/data : 容器卷,宿主机地址:docker内部地址
    6. redis:6.0.8 : redis镜像和版本号
    7. --cluster-enabled yes : 开启redis集群
    8. --appendonly yes : 开启持久化
    9. --port 6386 : redis端口号
  • 节点 一 ~ 六
    • Redis集群中的各个节点,需要开放一个端口,同其他节点建立连接,用于接收心跳数据等操作。也就是说,redis-node1节点,开放6379端口供client连接时,同时提供16379端口(10000 + 6379),供其他Redis节点连接。
      • springBoot连接失败,因为内部重定向到了172这个docker的内网IP
    • 通过–net host,指定网络类型为host,使得容器与宿主机使用同一网络,从而规避了这类问题
      • window不行
  1. # 我 centos
  2. # docker rm -f redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5 redis-node-6
  3. docker 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 6001
  4. docker 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 6002
  5. docker 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 6003
  6. docker 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 6004
  7. docker 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 6005
  8. docker 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
  9. # windows
  10. ## -v /D/docker/redis-share/redis-node-1:/data 挂载磁盘会导致主从切换失败
  11. ## --network host windows无法使用这个,会导致外部无法连接
  12. 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 6001
  13. docker 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 6002
  14. docker 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 6003
  15. docker 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 6004
  16. docker 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 6005
  17. docker 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节点

  1. # 进入node1容器内
  2. docker exec -it redis-node-1 bash
  3. # 构建集群关系 (注意,进入docker容器后才能执行一下命令,且注意自己的真实IP地址 )
  4. # --net host(windows不能用这个 -p -p 可以使用)
  5. 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
  6. # --net host(windows不能用这个) windows ok
  7. redis-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
  8. # my windows
  9. # 可以使用 172.17.0.2~7 ( ` docker network inspect bridge ` 查看), 也可以直接使用docker的IP(windos ` ipconfig ` 以太网适配器 vEthernet (WSL))
  10. 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
  11. # my centos
  12. redis-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-构建集群关系.png

进入redis

  1. redis-cli -p 6001 (因为指定了redis启动的端口,所以cli必须指定端口:1-6)

查看集群状态

  1. # 集群信息
  2. cluster info
  3. # 集群 节点 - 状态
  4. cluster nodes
  5. # 检查集群
  6. redis-cli --cluster check 127.0.0.1:6002
  • 随机 master - slave 对应

redis查看集群节点信息.png

数据存储

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

  • (error) MOVED 12706 127.0.0.1:6003 ······

redis集群存储.png

主从容错切换迁移

测试内容:master挂了,slave是否会启动 (当前测试 6001挂了,他的小弟6006会不会启动。<以实际情况为准>)

  1. stop 6001 docker stop redis-node-1
  2. 去其他节点查看 节点状态
    1. docker exec -it redis-node-2 bash
    2. redis-cli -p 6002 -c
    3. cluster nodes
    4. redis查看集群节点信息-主从容错.png

Windows出现没有切换成功

查看slave节点日志

  1. # 启动
  2. 1:S 25 Jan 2022 08:31:54.693 * MASTER <-> REPLICA sync started
  3. 1:S 25 Jan 2022 08:31:54.693 * Non blocking connect for SYNC fired the event.
  4. 1:S 25 Jan 2022 08:31:54.693 * Master replied to PING, replication can continue...
  5. 1:S 25 Jan 2022 08:31:54.693 * Partial resynchronization not possible (no cached master)
  6. 1:S 25 Jan 2022 08:31:54.694 * Full resync from master: b9c9d2d98e62a2b2d248aa070e73f4ecc622f7dc:0
  7. 1:S 25 Jan 2022 08:31:54.804 * MASTER <-> REPLICA sync: receiving 175 bytes from master to disk
  8. 1:S 25 Jan 2022 08:31:54.805 * MASTER <-> REPLICA sync: Flushing old data
  9. 1:S 25 Jan 2022 08:31:54.805 * MASTER <-> REPLICA sync: Loading DB in memory
  10. 1:S 25 Jan 2022 08:31:54.807 # Failed trying to load the MASTER synchronization DB from disk
  11. # 选举 6.0.8
  12. 1:S 25 Jan 2022 08:26:50.300 * MASTER <-> REPLICA sync started
  13. 1:S 25 Jan 2022 08:26:50.300 # Error condition on socket for SYNC: Operation now in progress
  14. # 选举 6.2.6
  15. 1:S 25 Jan 2022 08:54:51.141 # Error condition on socket for SYNC: Connection refused
  16. 1:S 25 Jan 2022 08:54:52.144 * Connecting to MASTER 127.0.0.1:6002
  • 怀疑是window的在进程中不允许对文件操作的问题照成的
    • 我把挂载的磁盘去掉用在挂载,就切换成功了

Linux(Centos )切换成功

redis集群-master宕机后重新选举成功.png

连接问题

  • 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

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

  1. - [通过配置路由表实现ip互通 ](https://www.cnblogs.com/brock0624/p/9788710.html) 我没有配置成功
  2. - 查看路由表 `route print`
  3. - 查看dockerIP `ipconfig` 太网适配器 vEthernet (WSL)
  4. - 添加路由 route -p add 172.17.0.0 MASK 255.255.255.0 xxx
  5. - 通过配置文件固定IP处理成功
  6. - cluster-announce-ip 192.168.0.65 (宿主机IP
  7. - `/D/docker/redis-share/redis-node-6/redis.conf:/etc/redis/redis.conf redis:6.0.8 redis-server /etc/redis/redis.conf`
  8. - 连接失败
  9. - redis.cnf 中的 bind 改成 bind 0.0.0.0 (这个我不确定,但是下面的防火墙是真的问题)
  10. - centos防火墙默认开启了的
  11. - firewal状态(防火墙)
  12. ```shell
  13. firewall-cmd --state
  14. systemctl status firewalld // 查看防火墙状态

停止firewal(防火墙)

  1. systemctl stop firewalld.service

禁止firewall开机启动(防火墙)

  1. systemctl disable firewalld.service

重启firewall(防火墙)

springboot 连接

maven

  1. <!--redis start -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-redis</artifactId>
  5. </dependency>
  6. <!--redis end -->

application.yml

  • 6001 6002 6003为初始的master节点,如果后面主从切换了之后,6001 6002 6003 不在时master了可以不出现错误
  • cluster.nodes 中必须要保证有一个节点不会挂,要不然就连不到了(3主三从 的情况像几乎不会这种情况)
  • 在节点关闭时,节点还没连接信息还是正常的会出现报错
  1. spring:
  2. redis:
  3. database: 0
  4. timeout: 10000 # 连接超时(毫秒)
  5. jedis:
  6. pool:
  7. max-active: 100 # 最大连接数(负值则无限制)
  8. max-idle: 100 # 最大空闲连接
  9. max-wait: -1 # 最大阻塞等待时间(负值则无限制)
  10. min-idle: 50 # 最小空闲连接
  11. cluster:
  12. max-redirects: 12 # 重定向的最大数量,比如第一台挂了,连第二台,第二台挂了连第三台,这个重新连接的最大数量
  13. nodes:
  14. # windows docker redis集群测试连接地址
  15. - 192.168.0.65:6001
  16. - 192.168.0.65:6002
  17. - 192.168.0.65:6003
  18. # centos docker redis集群测试连接地址
  19. - 192.168.126.138:6001
  20. - 192.168.126.138:6002
  21. - 192.168.126.138:6003

测试

  1. import org.junit.jupiter.api.Test;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.boot.test.context.SpringBootTest;
  4. import org.springframework.data.redis.core.StringRedisTemplate;
  5. @SpringBootTest
  6. class SpringbootRedisShareApplicationTests {
  7. @Autowired
  8. private StringRedisTemplate stringRedisTemplate;
  9. @Test
  10. void contextLoads() {
  11. stringRedisTemplate.opsForValue().set("das","dasdd");
  12. }
  13. }