Docker-compose搭建redis一主双从三哨兵

Docker-compose搭建redis一主双从三哨兵

  • 概述
    • 架构图
    • 服务器环境
    • docker编排文件
      • master
      • slave
    • redis主从配置
    • 启动主从容器
      • 验证redis主从
    • 添加哨兵
    • 启动哨兵
    • 验证failover(故障转移)
    • 填坑
    • springboot连接redis哨兵集群
      • pom添加依赖
      • yml配置连接信息

概述

Redis哨兵为Redis提供了高可用性。实际上这意味着你可以使用哨兵模式创建一个可以不用人为干预而应对各种故障的Redis部署。

哨兵模式还提供了其他的附加功能,如监控,通知,为客户端提供配置。

下面是在宏观层面上哨兵模式的功能列表:

  1. 监控:哨兵不断的检查master和slave是否正常的运行。
  2. 通知:当监控的某台Redis实例发生问题时,可以通过API通知系统管理员和其他的应用程序。
  3. 自动故障转移:如果一个master不正常运行了,哨兵可以启动一个故障转移进程,将一个slave升级成为master,其他的slave被重新配置使用新的master,并且应用程序使用Redis服务端通知的新地址。
  4. 配置提供者:哨兵作为Redis客户端发现的权威来源:客户端连接到哨兵请求当前可靠的master的地址。如果发生故障,哨兵将报告新地址。

架构图

在这里插入图片描述

服务器环境

准备三台主机:172.20.10.27,172.20.10.28,172.20.10.29,分别安装Docker及docker-compose。

docker编排文件

分别在三台主机的/usr/local/redis目录下创建docker-compose.yml,内容如下:

master

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: "3"
services:
  redis-master:
    image: redis
    container_name: redis-master
    restart: always
    privileged: true
    environment:
      - TZ=Asia/Shanghai
    ports:
      - "6379:6379"
    volumes:
      - /usr/local/redis/data:/data
      - /usr/local/redis/conf/redis-master.conf:/usr/local/etc/redis/redis.conf
    command: redis-server /usr/local/etc/redis/redis.conf
  redis-sentinel:
    image: redis
    container_name: redis-sentinel
    restart: always
    privileged: true
    environment:
      - TZ=Asia/Shanghai
    ports:
      - "26379:26379"
    volumes:
      - /usrl/local/redis/conf/redis-sentinel.conf:/usr/local/etc/redis/sentinel.conf
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf

slave

两个从节点的编排文件内容一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: "3"
services:
  redis-slave:
    image: redis
    container_name: redis-slave
    restart: always
    privileged: true
    environment:
      - TZ=Asia/Shanghai
    ports:
      - "6379:6379"
    volumes:
      - /usr/local/redis/data:/data
      - /usr/local/redis/conf/redis-slave.conf:/usr/local/etc/redis/redis.conf
    command: redis-server /usr/local/etc/redis/redis.conf
  redis-sentinel:
    image: redis
    container_name: redis-sentinel
    restart: always
    privileged: true
    environment:
      - TZ=Asia/Shanghai
    ports:
      - "26379:26379"
    volumes:
      - /usr/local/redis/conf/redis-sentinel.conf:/usr/local/etc/redis/sentinel.conf
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf

redis主从配置

master节点服务器/usr/local/redis/conf/redis-master.conf创建挂载的配置文件:

1
2
3
4
5
6
bind 0.0.0.0
protected-mode no
port 6379
#主节点也需要设置主节点的授权密码,因为角色会发生转变
masterauth 123456
requirepass 123456

slave节点配置,在两个从服务器/usr/local/redis/conf/redis-slave.conf创建挂载的配置文件:

1
2
3
4
5
6
7
8
9
10
bind 0.0.0.0
protected-mode no
port 6379
slaveof 172.20.10.27 6379
#主节点也需要设置主节点的授权密码,因为角色会发生转变
masterauth 123456
requirepass 123456
#因为使用docker部署的redis服务默认上报的元数据信息是docker容器内部ip与port,这里显示声明物理机的ip与port
slave-announce-ip 172.20.10.28
slave-announce-port 6379

启动主从容器

分别在三台服务器/usr/local/redis目录下执行docker-compose up -d命令创建启动容器。第一次执行该命令时docker-compsoe会根据yml文件中配置的image信息自动下载镜像。
在这里插入图片描述
可以看到名称为redis-master的容器状态为up,宿主机6379端口映射到容器内部6379端口,两台从主机信息雷同。

验证redis主从

主服务器执行,进入到容器内部

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@localhost ~]# docker exec -it redis-master bash
#在容器里启动一个redis客户端,并授权
root@4a7fb46b57d3:/data# redis-cli
127.0.0.1:6379> auth 123456
#查看服务信息
127.0.0.1:6379> info
#主要查看一下信息
# Replication
role:master
connected_slaves:2
slave0:ip=172.20.10.28,port=6379,state=online,offset=5105669955,lag=0
slave1:ip=172.20.10.29,port=6379,state=online,offset=5105669998,lag=0

#ps对于从主机还要查看master_link_status这个属性值。slave上这个属性值为up就说明主从复制是OK的,否则就有问题。如果从机状态不为up,首先排查主机的端口是否被限,然后查看redis日志排查原因
role:slave
master_link_status:up

#主机点写入一个数据
127.0.0.1:6379> set test 123
OK
127.0.0.1:6379> get test
"123"
#退出redis客户端连接
127.0.0.1:6379> exit
#退出docker容器
root@4a7fb46b57d3:/data# exit

#登录到从节点去查看数据是否复制成功
127.0.0.1:6379> get test
"123"

添加哨兵

三个节点/usr/local/redis/conf/redis-sentinel.conf创建哨兵服务挂载的配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
port 26379

daemonize no

pidfile "/var/run/redis-sentinel.pid"

logfile ""

sentinel myid 79c1f8276a8fedd78a9f987da8c85fce0ea7f751
sentinel deny-scripts-reconfig yes

dir "/tmp"

# 这里配置监控主服务的IP 端口 , 2表示两台机器判定主被动下线后,就进行failover(故障转移),这里需要遵循过半机制
sentinel monitor mymaster 172.20.10.27 6379 2

sentinel auth-pass mymaster 123456

sentinel config-epoch mymaster 3

sentinel leader-epoch mymaster 3

#同样需要声明物理机的ip与port
sentinel announce-ip "172.20.10.28"
sentinel announce-port 26379

启动哨兵

因为之前创建的docker-compose.yml文件中已经配置了哨兵的容器信息,所以直接启动就可以了。

1
2
3
4
#停止并删除之前创建的容器
docker-compose down
#创建并启动容器
docker-compose up -d

在这里插入图片描述
查看docker sentinel日志
执行

1
2
3
4
5
docker logs redis-sentinel
 +monitor master mymaster 172.20.10.27 6379 quorum 2
 +slave slave 172.20.20.28:6379 172.20.20.28 6379 @ mymaster 172.20.10.27 6379
 +slave slave 172.20.20.29:6379 172.20.20.29 6379 @ mymaster 172.20.10.27 6379
 可以看到sentinel已经监控到了一主双从的信息。

或者进如sentinel容器内部,连接客户端来查看信息:

1
2
3
4
5
6
7
8
9
root@52adc847e9c6:/data# redis-cli -p 26379
127.0.0.1:26379> info
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=172.20.10.27:6379,slaves=2,sentinels=3

验证failover(故障转移)

停止运行主服务器的上redis-master容器,然后查看redis-sentinel容器的日志追加了如下信息。
+odown master mymaster 172.20.10.27 6379 #quorum 3/2:表示名为mymaster主从中172.20.10.27这个主节点被哨兵监控到客观宕机。
+switch-master mymaster 172.20.10.27 6379 172.20.10.28 6379:表示配置变更,主服务器的 IP 和地址已由172.20.10.27 6379变更为172.20.10.28 6379

1
2
3
4
5
6
7
8
9
10
11
12
 [root@localhost ~]# docker stop redis-master
 redis-master
 [root@localhost ~]# docker logs redis-sentinel
 1:X 01 Jun 2020 17:31:50.435 # +sdown master mymaster 172.20.10.27 6379
 1:X 01 Jun 2020 17:31:50.458 # +new-epoch 4
 1:X 01 Jun 2020 17:31:50.460 # +vote-for-leader 79c1f8276a8fedd78a9f987da8c85fce0ea7f751 4
 1:X 01 Jun 2020 17:31:50.527 # +odown master mymaster 172.20.10.27 6379 #quorum 3/2
 1:X 01 Jun 2020 17:31:50.527 # Next failover delay: I will not start a failover before  Mon Jun  1 17:37:50 2020
 1:X 01 Jun 2020 17:31:51.708 # +config-update-from sentinel 79c1f8276a8fedd78a9f987da8c85fce0ea7f751 172.20.10.28 26379 @ mymaster 172.20.10.27 6379
 1:X 01 Jun 2020 17:31:51.708 # +switch-master mymaster 172.20.10.27 6379 172.20.10.28 6379
 1:X 01 Jun 2020 17:31:51.708 * +slave slave 172.20.10.29:6379 172.20.10.29 6379 @   mymaster 172.20.10.28 6379
 1:X 01 Jun 2020 17:31:51.708 * +slave slave 172.20.10.27:6379 172.20.10.27 6379 @ mymaster 172.20.10.28 6379

进入容器中验证28节点的角色已经转变为master,且连接了一个从节点29。因为此时27节点还未恢复。

1
2
3
4
5
6
7
8
9
[root@localhost ~]# docker exec -it redis-slave bash
root@19259dab997c:/data# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> info
# Replication
role:master
connected_slaves:1
slave0:ip=172.20.10.29,port=6379,state=online,offset=6198208362,lag=0

重启27节点上的redis-master容器中redis的信息,证明redis-master状态从down转变为up时,角色为slave,主节点信息为28。

1
2
3
4
5
6
7
8
9
10
11
[root@localhost ~]# docker start redis-master
redis-master
[root@localhost ~]# docker exec -it redis-master bash
root@4a7fb46b57d3:/data# redis-cli
127.0.0.1:6379> auth 123456
127.0.0.1:6379> info
# Replication
role:slave
master_host:172.20.10.28
master_port:6379
master_link_status:up

填坑

  • 因为使用docker来部署redis,所以slave和sentinel上报的元数据信息是docker容器内部ip与port,服务之间无法正常访问,所以:从节点需要配置宿主机的ip和端口:slave-announce-ip 172.20.10.28,slave-announce-port 6379。每个sentinel节点需要配置:sentinel announce-ip “172.20.10.28”
    sentinel announce-port 26379。
  • 使用docker挂载配置文件时需要注意配置文件的版本与redis镜像版本一致,否则会导致容器启动失败。

springboot连接redis哨兵集群

pom添加依赖

1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

yml配置连接信息

1
2
3
4
5
6
7
spring:
  redis:
    sentinel:
      master: mymaster
      nodes: 172.20.10.27:26379,172.20.10.28:26379,172.20.10.29:26379
    timeout: 6000ms
    database: 0