一、准备工作
需要先创建一个docker网络,类型为桥接网络,后面会将redis主从节点和sentinel集群都加入到这网络中,目的是保证全部节点的相互连通。
# 创建名称为redis-net的桥接网络
docker network create -d bridge redis-net
注:其实可以不用特意创建一个网络,默认所有节点会自动加入到名称为bridge的桥接网络中,这个网络是默认已存在的
二、部署redis节点
- 在自己电脑上建一个文件夹,然后放一个redis-6380.conf配置文件,这个配置文件直接拷贝的默认的redis.conf配置文件(实不相瞒,我就是用的redis官网的redis4.0.14配置文件),只需修改如下两个配置:
#bind 127.0.0.1
protected-mode no
- 在命令行运行以下命令,用来在docker容器中启动一个redis节点
docker run -d -p 6380:6379 --name redis-node-6380 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/redis-6380.conf,target=/etc/redis.conf redis:4.0.14 redis-server /etc/redis.conf
-d
表示在后台运行-p 6380:6379
表示将容器中的6379端口绑定到宿主机的6380端口,这样就可以在容器外部使用localhost:6380访问这个redis--name redis-node-6380
表示容器名称是redis-node-6380--network redis-net
表示加入redis-net网络--mount type=bind,source=/home/debo/dockerData/redis/redis-6380.conf,target=/etc/redis.conf
表示将宿主机的redis-6380.conf文件挂载到容器中/etc/redis.conf下redis:4.0.14 redis-server /etc/redis.conf
表示使用镜像redis:4.0.14启动容器,如果没有这镜像,会自动从镜像仓库下载的,同时启动成功后执行redis-server命令并使用容器中的/etc/redis.conf作为配置文件
- 将redis-6380.conf文件复制两份,分别重命名为redis-6381.conf和redis-6382.conf,然后依次执行如下命令,完成另外两个redis节点的部署
docker run -d -p 6381:6379 --name redis-node-6381 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/redis-6381.conf,target=/etc/redis.conf redis:4.0.14 redis-server /etc/redis.conf
docker run -d -p 6382:6379 --name redis-node-6382 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/redis-6382.conf,target=/etc/redis.conf redis:4.0.14 redis-server /etc/redis.conf
以上操作完成后,就将3个独立的redis节点部署完成了。可以在宿主机(也就是自己电脑)命令行中执行命令redis-cli -p 6380
看看是否部署成功
三、设置redis主从复制
以redis-node-6380作为主节点,redis-node-6381和redis-node-6382作为从节点,实现一主两从架构。
- 运行命令
docker network inspect redis-net
会输出如下信息
"Containers": {
"1411e74f1619f6d4268fc0f9f70f89d9ba211729db49906cbc568d9f10c41ddc": {
"Name": "redis-node-6382",
"EndpointID": "0e3429f73ade0a9b972cf90fb5b4d299914cbafb1788f4c72aa00e6cf16a536f",
"MacAddress": "02:42:ac:12:00:04",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": ""
},
"74dbf13733caab38979141899dad954a3b64e9674b78e1378160cbdea203343f": {
"Name": "redis-node-6381",
"EndpointID": "c87bc4327a7fc471339ce04d465133745c460a70304854d33ec760df8e7ad7c6",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"9e1230cfc3a79f7dfe01397f1f473a4d2809c7ebe909267fd7edd45472641c19": {
"Name": "redis-node-6380",
"EndpointID": "5121006f5c432723d764cf9b8a06b8db11b7f10d643a28ef9be0c48e959ea592",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
}
可见redis-node-6380节点的IP地址为172.18.0.2
2. 修改redis-6381.conf和redis-6382.conf,设置从节点,要修改的配置如下:
slaveof 172.18.0.2 6379
- 重启redis-node-6381和redis-node-6382两个容器
docker restart redis-node-6381
docker restart redis-node-6382
完成以上步骤后,一主两从的redis高可用架构就部署好了,但是当主节点挂掉以后,从节点提升为主节点这动作不是自动完成的,需要我们手动去将其中一个从节点提升为主节点,同时还需要修改调用方的主节点地址,这个太麻烦了,所以我们需要sentinel集群,它可以在主节点挂掉以后自动将其中一个从节点提升为主节点,当主节点恢复以后,自动将老的主节点设置为新主节点的从节点,同时主节点地址对调用方透明。
四、部署sentinel集群
- 在自己电脑上建一个文件夹,然后放一个sentinel-26380.conf配置文件,这个配置文件直接拷贝的默认的sentinel.conf配置文件,只需修改如下两个配置:
protected-mode no
sentinel monitor mymaster 172.18.0.2 6379 2
- 在命令行运行以下命令,用来在docker容器中启动一个sentinel节点
docker run -d -p 26380:26379 --name sentinel-node-26380 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/sentinel-26380.conf,target=/etc/sentinel.conf redis:4.0.14 redis-sentinel /etc/sentinel.conf
- 将sentinel-26380.conf文件复制两份,分别重命名为sentinel-26381.conf和sentinel-26382.conf,然后依次执行如下命令,完成另外两个sentinel节点的部署
docker run -d -p 26381:26379 --name sentinel-node-26381 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/sentinel-26381.conf,target=/etc/sentinel.conf redis:4.0.14 redis-sentinel /etc/sentinel.conf
docker run -d -p 26382:26379 --name sentinel-node-26382 --network redis-net --mount type=bind,source=/home/debo/dockerData/redis/sentinel-26382.conf,target=/etc/sentinel.conf redis:4.0.14 redis-sentinel /etc/sentinel.conf
以上操作完成后,含有三个节点的sentinel集群就部署完成了
五、使用Jedis连接sentinel集群进行验证
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
/**
* @author debo
* @date 2020-01-03
*/
public class SentinelTest {
public static void main(String[] args) {
String masterName = "mymaster";
// sentinel地址集合
Set<String> addresses = new HashSet<>();
addresses.add("localhost:26380");
addresses.add("localhost:26381");
addresses.add("localhost:26382");
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, addresses);
Jedis jedis = jedisSentinelPool.getResource();
jedis.set("testkey", "123321");
System.out.println();
}
}
可以发现,每次的jedis使用的都是主节点,当我们将主节点容器停止后,过一会儿再运行这例子,发现jedis使用的是新的主节点。(JedisSentinelPool中每次拿到的都是主节点连接,无法拿到从节点连接,如果要拿从节点信息,可以自己扩展)
六、sentinel集群监控多组redis主从节点
sentinel集群可以监控多组redis主从节点,假设现在要增加监控另一组redis主从节点,只需要将另一组的redis主节点信息添加到sentinel配置文件中即可,如:
sentinel monitor mymaster 172.18.0.2 6379 2
sentinel monitor mymaster1 172.18.0.5 6379 2
相应地,业务代码中如果要同时使用两组主从节点,那么代码可以调整如下:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
/**
* @author debo
* @date 2020-01-03
*/
public class SentinelTest {
public static void main(String[] args) {
String masterName = "mymaster";
String master1Name = "mymaster1";
// sentinel地址集合
Set<String> addresses = new HashSet<>();
addresses.add("localhost:26380");
addresses.add("localhost:26381");
addresses.add("localhost:26382");
// 监控第一组redis主从节点
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, addresses);
Jedis jedis = jedisSentinelPool.getResource();
jedis.set("first", "123321");
System.out.println();
// 监控第二组redis主从节点
JedisSentinelPool jedisSentinelPool1 = new JedisSentinelPool(master1Name, addresses);
Jedis jedis1 = jedisSentinelPool1.getResource();
jedis1.set("second", "123321");
System.out.println();
}
}
需要说明的是,受sentinel集群监控的这两组redis主从节点是相互独立的,互不影响(不同于redis分片集群)。