环境
- 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-6
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
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
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
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
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
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
# 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 6001
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
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
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
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
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节点
# 进入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 ok
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
# 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 centos
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
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 bash
redis-cli -p 6002 -c
cluster nodes
Windows出现没有切换成功
查看slave节点日志
# 启动
1:S 25 Jan 2022 08:31:54.693 * MASTER <-> REPLICA sync started
1: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:0
1:S 25 Jan 2022 08:31:54.804 * MASTER <-> REPLICA sync: receiving 175 bytes from master to disk
1:S 25 Jan 2022 08:31:54.805 * MASTER <-> REPLICA sync: Flushing old data
1:S 25 Jan 2022 08:31:54.805 * MASTER <-> REPLICA sync: Loading DB in memory
1:S 25 Jan 2022 08:31:54.807 # Failed trying to load the MASTER synchronization DB from disk
# 选举 6.0.8
1:S 25 Jan 2022 08:26:50.300 * MASTER <-> REPLICA sync started
1:S 25 Jan 2022 08:26:50.300 # Error condition on socket for SYNC: Operation now in progress
# 选举 6.2.6
1:S 25 Jan 2022 08:54:51.141 # Error condition on socket for SYNC: Connection refused
1: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状态(防火墙)
```shell
firewall-cmd --state
systemctl 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: 0
timeout: 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;
@SpringBootTest
class SpringbootRedisShareApplicationTests {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void contextLoads() {
stringRedisTemplate.opsForValue().set("das","dasdd");
}
}