master 节点一定要和Slave节点分开部署。最好一个节点一台服务器,不然搭建好之后,通过哨兵动态选举获取的 主节点ip地址 是容器内部地址,无法从外部访问。因为使用docker部署的时候,主节点和从节点部署在一起,从节点向主节点注册的时候。会使用容器ip进行注册,所以导致程序获取到了容器ip,所以导致虽然拿到了主节点但是不能使用,提示找不到主机。
环境准备
新建四台cento7 虚拟机,网络使用桥接模式(建议ip使用固定ip)。
软件环境
安装docker(每台虚拟机都安装)
获取redis:6.2.6 版本image(镜像)
docker pull redis:6.2.6
mkdir -p /home/redis
cd /home/redis
mkdir -p redisMaster/conf redisMaster/data
在conf 目录下创建,下面Run的时候使用。
myredisMaster.conf
# 所有主机都可以连接
bind 0.0.0.0
# 关闭保护模式
protected-mode no
# 端口号
port 6379
tcp-backlog 511
# 密码
requirepass ksh@@@
always-show-logo yes
save 900 1
save 300 10
save 60 10000
# 主节点的密码,如果主节点挂了。再次启动作为从节点链接新的主节点使用(所有节点密码保持一致)
masterauth ksh@@@
docker run -d --name master -p 6379:6379 -v /home/redis/redisMaster/conf/myredisMaster.conf:/etc/redis/redis.conf -v /home/redis/redisMaster/data/:/data --restart=always redis:6.2.6 /etc/redis/redis.conf
// 开放6379 端口号
firewall-cmd --zone=public --add-port=6379/tcp --permanent
//重启防火墙使其生效
firewall-cmd --reload
//查看目前开放的端口号-检查是否开启成功
firewall-cmd --list-ports
cd /home/redis
mkdir -p Slave01/conf Slave01/data
查看主节点ip地址
docker inspect master
//ip地址
172.17.0.2
在conf 目录下创建,下面Run的时候使用。
myredisSlave01.conf
bind 0.0.0.0
protected-mode no
port 6378
tcp-backlog 511
always-show-logo yes
requirepass ksh@@@
save 900 1
save 300 10
save 60 10000
# 主从复制-主节点
replicaof 主节点ip 6379
# 主节点的密码
masterauth ksh@@@
docker run -d --name Slave01 -p 6378:6378 -v /home/redis/Slave01/conf/myredisSlave01.conf:/etc/redis/redis.conf -v /home/redis/Slave01/data/:/data --restart=always redis:6.2.6 /etc/redis/redis.conf
info replication
从上面图片中可以看到-目前的master节点下已经有了一个从节点,状态为在线状态。
state=online 特别注意:如果这个状态不是online说明主从同步失败,请检查从节点是否连接上主节点,可以查看从节点日志。
如果出现划红线部分,就是正常同步,从节点已经链接到主节点。
//开放6378 端口的防火墙
firewall-cmd --zone=public --add-port=6378/tcp --permanent
// 重启防火墙使其生效
firewall-cmd --reload
//查看目前开放的防火墙
firewall-cmd --list-ports
从上面图中可以看到,在从节点获取到了 主节点写入的数据 康世行
info replication
从上面图中可以看到,此从节点指向的 master 节点的 ip和端口号以及master 节点的状态。
cd /home/redis
mkdir -p Slave02/conf Slave02/data
在conf 目录下创建,下面Run的时候使用。
myredisSlave02.conf
bind 0.0.0.0
protected-mode no
port 6377
tcp-backlog 511
always-show-logo yes
requirepass ksh@@@
save 900 1
save 300 10
save 60 10000
# 主从复制-主节点
replicaof 主节点ip 6379
# 主节点的密码
masterauth ksh@@@
docker run -d --name Slave02 -p 6377:6377 -v /home/redis/Slave02/conf/myredisSlave02.conf:/etc/redis/redis.conf -v /home/redis/Slave02/data/:/data --restart=always redis:6.2.6 /etc/redis/redis.conf
info replication
从图片中可以看出,多了个从节点slave1
connected_slaves:2 //从节点数量
//开放6377 端口的防火墙
firewall-cmd --zone=public --add-port=6377/tcp --permanent
// 重启防火墙使其生效
firewall-cmd --reload
//查看目前开放的防火墙
firewall-cmd --list-ports
从上面图中可以看到一样可以获取到主节点的数据 康世行
info replication
从上面图中可以看到,哨兵节点会监控 主节点和从节点。当主节点不可用的时候,会在从节点中选举一个新主节点。程序原来直接连接主节点,当主节点不可用。程序的写操作就不可用,现在程序连接哨兵节点,通过哨兵节点获取当前redis的主节点。就不会存在和主节点帮死的情况了。可以理解为解耦,“没有什么是加一层解决不了的” 通过学习和应用了怎么多中间件,才发现这句话确实有道理!
//哨兵无法把容器里的配置写入到宿主机对应的配置文件里-暂时未解决
WARNING: Sentinel was not able to save the new configuration on disk!!!: Device or resource busy
cd /home/redis
mkdir -p sentinel01/conf sentinel01/data
在conf 目录下创建,下面Run的时候使用。
myredisSentinel01.conf
port 26379
sentinel monitor mymaster 主节点ip 6379 1
sentinel auth-pass mymaster ksh@@@
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 900000
sentinel parallel-syncs mymaster 1
docker run -d --name sentinel01 -p 26379:26379 -v /home/redis/sentinel01/conf/myredisSentinel01.conf:/etc/redis/redis.conf -w=/etc/redis/ -v /home/redis/sentinel01/data/:/data --restart=always redis:6.2.6 /etc/redis/redis.conf --sentinel
//参数解释
-w=/etc/redis/ 指定工作目录
// 开放 26379 端口
firewall-cmd --zone=public --add-port=26379/tcp --permanent
//重启防火墙-使其端口生效
firewall-cmd --reload
//查看开放的端口是否生效
firewall-cmd --list-ports
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.1</version>
</dependency>
package com.example.likoudemo.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.Arrays;
import java.util.HashSet;
/**
* @Description TODO
* @ClassName redisTest
* @Author 康世行
* @Date 21:02 2022/6/27
* @Version 1.0
**/
public class redisTest {
public static void main(String[] args) {
//这里我们直接使用JedisSentinelPool来获取Master节点
//需要把三个哨兵的地址都填入 mymaster
try (JedisSentinelPool pool = new JedisSentinelPool("mymaster",
new HashSet<>(Arrays.asList("192.168.96.250:26379")),"ksh@@@")) {
Jedis jedis = pool.getResource(); //直接询问并得到Jedis对象,这就是连接的Master节点
jedis.set("test", "哨兵动态调整master节点测试"); //直接写入即可,实际上就是向Master节点写入
Jedis jedis2 = pool.getResource(); //再次获取
System.out.println(jedis2.get("test")); //读取操作
} catch (Exception e) {
e.printStackTrace();
}
}
}