一、Redis-Sentinel简介
Sentinel(哨岗、哨兵)是Redis的高可用性(high availability)解决方案:由一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
二、安装docker-compose
Linux上我们可以从Github上下载它的二进制包来使用,最新发行的版本地址:https://github.com/docker/compose/releases。
1、运行以下命令以下载Docker Compose的v2.11.0版本
[root@localhost ~]# wget -O /usr/bin/docker-compose https://github.com/docker/compose/releases/download/v2.11.0/docker-compose-linux-x86_64
2、授权可执行权限
[root@localhost ~]# chmod +x /usr/bin/docker-compose
3、测试是否安装成功
[root@localhost ~]# docker-compose -v
Docker Compose version v2.11.0
三、部署Redis、Redis-Sentinel
1、创建Redis-Sentinel目录
[root@localhost ~]# mkdir -p /opt/redis-sentinel
2、创建docker-compose配置文件
[root@localhost ~]# cd /opt/redis-sentinel
[root@localhost redis-sentinel]# vim docker-compose.yml
version: '3.3'
services:
redis-sentinel-1:
image: redis:6.2.7
container_name: redis-sentinel-1
restart: always
privileged: true
ports:
- '26379:26379'
depends_on:
- redis-master
- redis-slave-1
- redis-slave-2
volumes:
- /opt/redis-sentinel/conf:/etc/redis
- /data/redis-sentinel/redis-sentinel-1:/data
environment:
TZ: "Asia/Shanghai"
command:
redis-sentinel /etc/redis/redis-sentinel-1.conf
redis-sentinel-2:
image: redis:6.2.7
container_name: redis-sentinel-2
restart: always
privileged: true
ports:
- '26380:26380'
depends_on:
- redis-master
- redis-slave-1
- redis-slave-2
volumes:
- /opt/redis-sentinel/conf:/etc/redis
- /data/redis-sentinel/redis-sentinel-2:/data
environment:
TZ: "Asia/Shanghai"
command:
redis-sentinel /etc/redis/redis-sentinel-2.conf
redis-sentinel-3:
image: redis:6.2.7
container_name: redis-sentinel-3
restart: always
privileged: true
ports:
- '26381:26381'
depends_on:
- redis-master
- redis-slave-1
- redis-slave-2
volumes:
- /opt/redis-sentinel/conf:/etc/redis
- /data/redis-sentinel/redis-sentinel-3:/data
environment:
TZ: "Asia/Shanghai"
command:
redis-sentinel /etc/redis/redis-sentinel-3.conf
redis-master:
image: redis:6.2.7
container_name: redis-master
restart: always
privileged: true
build:
network: host
environment:
TZ: "Asia/Shanghai"
volumes:
- /opt/redis-sentinel/conf/redis-master.conf:/etc/redis/redis-master.conf
- /data/redis-sentinel/redis-master:/data
command:
redis-server /etc/redis/redis-master.conf
redis-slave-1:
image: redis:6.2.7
container_name: redis-slave-1
restart: always
privileged: true
build:
network: host
depends_on:
- redis-master
environment:
TZ: "Asia/Shanghai"
volumes:
- /opt/redis-sentinel/conf/redis-slave-1.conf:/etc/redis/redis-slave-1.conf
- /data/redis-sentinel/redis-slave-1:/data
command:
redis-server /etc/redis/redis-slave-1.conf
redis-slave-2:
image: redis:6.2.7
container_name: redis-slave-2
restart: always
privileged: true
build:
network: host
depends_on:
- redis-master
environment:
TZ: "Asia/Shanghai"
volumes:
- /opt/redis-sentinel/conf/redis-slave-2.conf:/etc/redis/redis-slave-2.conf
- /data/redis-sentinel/redis-slave-2:/data
command:
redis-server /etc/redis/redis-slave-2.conf
3、创建Redis配置文件
# Master
[root@localhost redis-sentinel]# mkdir conf
[root@localhost redis-sentinel]# vim conf/redis-master.conf
# 绑定IP地址
bind 0.0.0.0
# 监听端口
port 6379
# 自定义密码
requirepass "123456"
# 超时时间
timeout 0
# 数据目录
dir "/data"
save 3600 1
save 300 100
save 60 10000
# PID文件
pidfile "/var/run/redis.pid"
# 日志文件
logfile "/tmp/redis.log"
appendfsync everysec
appendonly yes
dbfilename "dump.rdb"
# 设定连接主节点所使用的密码
masterauth "123456"
# Slave1
[root@localhost redis-sentinel]# vim conf/redis-slave-1.conf
# 绑定IP地址
bind 0.0.0.0
# 监听端口
port 6380
# 自定义密码
requirepass "123456"
# 超时时间
timeout 0
# 数据目录
dir "/data"
save 3600 1
save 300 100
save 60 10000
# PID文件
pidfile "/var/run/redis.pid"
# 日志文件
logfile "/tmp/redis.log"
appendfsync everysec
appendonly yes
dbfilename "dump.rdb"
# 设定连接主节点所使用的密码
masterauth "123456"
# 设置主Redis的地址和端口
replicaof redis-master 6379
# Slave2
[root@localhost redis-sentinel]# vim conf/redis-slave-2.conf
# 绑定IP地址
bind 0.0.0.0
# 监听端口
port 6381
# 自定义密码
requirepass "123456"
# 超时时间
timeout 0
# 数据目录
dir "/data"
save 3600 1
save 300 100
save 60 10000
# PID文件
pidfile "/var/run/redis.pid"
# 日志文件
logfile "/tmp/redis.log"
appendfsync everysec
appendonly yes
dbfilename "dump.rdb"
# 设定连接主节点所使用的密码
masterauth "123456"
# 设置主Redis的地址和端口
replicaof redis-master 6379
4、创建Redis-Sentinel配置文件
# sentinel-1
[root@localhost redis-sentinel]# vim conf/redis-sentinel-1.conf
# 哨兵的端口号
port 26379
# 设定密码认证
requirepass "123456"
# sentinel日志
logfile "/tmp/redis-sentinel.log"
# PID文件
pidfile "/var/run/redis-sentinel.pid"
# 数据目录
dir "/data"
# 配置哨兵的监控参数
# 格式:sentinel monitor <master-name> <ip> <redis-port> <quorum>
# master-name是为这个被监控的master起的名字
# ip是被监控的master的IP或主机名。因为Docker容器之间可以使用容器名访问,所以这里写master节点的容器名
# redis-port是被监控节点所监听的端口号
# quorom设定了当几个哨兵判定这个节点失效后,才认为这个节点真的失效了
sentinel monitor redis-sentinel redis-master 6379 2
# 连接主节点的密码
# 格式:sentinel auth-pass <master-name> <password>
sentinel auth-pass redis-sentinel 123456
# master在连续多长时间无法响应PING指令后,就会主观判定节点下线,默认是30秒
# 格式:sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds redis-sentinel 5000
# 指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行同步,这个数字越小,完成failover所需的时间就越长
sentinel parallel-syncs redis-sentinel 1
# 故障转移的超时时间,默认3分钟
sentinel failover-timeout redis-sentinel 5000
# 解析主机名(只有6.2以上版本的)
sentinel resolve-hostnames yes
# sentinel-2
[root@localhost redis-sentinel]# vim redis-sentinel-2.conf
# 哨兵的端口号
port 26380
# 设定密码认证
requirepass "123456"
# sentinel日志
logfile "/tmp/redis-sentinel.log"
# PID文件
pidfile "/var/run/redis-sentinel.pid"
# 数据目录
dir "/data"
# 配置哨兵的监控参数
# 格式:sentinel monitor <master-name> <ip> <redis-port> <quorum>
# master-name是为这个被监控的master起的名字
# ip是被监控的master的IP或主机名。因为Docker容器之间可以使用容器名访问,所以这里写master节点的容器名
# redis-port是被监控节点所监听的端口号
# quorom设定了当几个哨兵判定这个节点失效后,才认为这个节点真的失效了
sentinel monitor redis-sentinel redis-master 6379 2
# 连接主节点的密码
# 格式:sentinel auth-pass <master-name> <password>
sentinel auth-pass redis-sentinel 123456
# master在连续多长时间无法响应PING指令后,就会主观判定节点下线,默认是30秒
# 格式:sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds redis-sentinel 5000
# 指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行同步,这个数字越小,完成failover所需的时间就越长
sentinel parallel-syncs redis-sentinel 1
# 故障转移的超时时间,默认3分钟
sentinel failover-timeout redis-sentinel 5000
# 解析主机名(只有6.2以上版本的)
sentinel resolve-hostnames yes
# sentinel-3
[root@localhost redis-sentinel]# vim redis-sentinel-3.conf
# 哨兵的端口号
port 26381
# 设定密码认证
requirepass "123456"
# sentinel日志
logfile "/tmp/redis-sentinel.log"
# PID文件
pidfile "/var/run/redis-sentinel.pid"
# 数据目录
dir "/data"
# 配置哨兵的监控参数
# 格式:sentinel monitor <master-name> <ip> <redis-port> <quorum>
# master-name是为这个被监控的master起的名字
# ip是被监控的master的IP或主机名。因为Docker容器之间可以使用容器名访问,所以这里写master节点的容器名
# redis-port是被监控节点所监听的端口号
# quorom设定了当几个哨兵判定这个节点失效后,才认为这个节点真的失效了
sentinel monitor redis-sentinel redis-master 6379 2
# 连接主节点的密码
# 格式:sentinel auth-pass <master-name> <password>
sentinel auth-pass redis-sentinel 123456
# master在连续多长时间无法响应PING指令后,就会主观判定节点下线,默认是30秒
# 格式:sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds redis-sentinel 5000
# 指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行同步,这个数字越小,完成failover所需的时间就越长
sentinel parallel-syncs redis-sentinel 1
# 故障转移的超时时间,默认3分钟
sentinel failover-timeout redis-sentinel 5000
# 解析主机名(只有6.2以上版本的)
sentinel resolve-hostnames yes
5、创建数据目录
[root@localhost redis-sentinel]# mkdir -p /data/redis-sentinel/{redis-master,redis-slave-1,redis-slave-2}
[root@localhost redis-sentinel]# mkdir -p /data/redis-sentinel/redis-sentinel-{1..3}
6、启动容器
[root@localhost redis-sentinel]# docker-compose up -d
7、查看容器运行状态
[root@localhost redis-sentinel]# docker-compose ps
NAME COMMAND SERVICE STATUS PORTS
redis-master "docker-entrypoint.s…" redis-master running 6379/tcp
redis-sentinel-1 "docker-entrypoint.s…" redis-sentinel-1 running 6379/tcp, 0.0.0.0:26379->26379/tcp
redis-sentinel-2 "docker-entrypoint.s…" redis-sentinel-2 running 6379/tcp, 0.0.0.0:26380->26380/tcp
redis-sentinel-3 "docker-entrypoint.s…" redis-sentinel-3 running 6379/tcp, 0.0.0.0:26381->26381/tcp
redis-slave-1 "docker-entrypoint.s…" redis-slave-1 running 6379/tcp
redis-slave-2 "docker-entrypoint.s…" redis-slave-2 running 6379/tcp
8、访问Redis
[root@localhost redis-sentinel]# docker exec -it redis-master redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.21.0.4,port=6380,state=online,offset=6551,lag=1
slave1:ip=172.21.0.3,port=6381,state=online,offset=6410,lag=1
master_failover_state:no-failover
master_replid:cf03aa830887e4d5d132944bc1728f0086859e71
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:6551
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:6551
9、主库写入测试数据,查询从库数据是否同步
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set domain www.yangxingzhen.com
OK
127.0.0.1:6379> get domain
"www.yangxingzhen.com"
# 从库查询数据
[root@localhost redis-sentinel]# docker exec -it redis-slave-1 redis-cli -p 6380
127.0.0.1:6380> auth 123456
OK
127.0.0.1:6380> get domain
"www.yangxingzhen.com"
[root@localhost redis-sentinel]# docker exec -it redis-slave-2 redis-cli -p 6381
127.0.0.1:6381> auth 123456
OK
127.0.0.1:6381> get domain
"www.yangxingzhen.com"
10、模拟主库宕机,验证sentinel是否起作用
[root@localhost redis-sentinel]# docker-compose stop redis-master
11、查看sentinel日志
[root@localhost redis-sentinel]# docker exec -it redis-sentinel-1 tail -fn 100 /tmp/redis-sentinel.log
1:X 05 Dec 2022 14:33:48.451 # Sentinel ID is c84944aa698217d88ae1b98cfa0d76bcff36bd7e
1:X 05 Dec 2022 14:33:48.452 # +monitor master redis-sentinel 172.21.0.2 6379 quorum 2
1:X 05 Dec 2022 14:33:48.454 * +slave slave 172.21.0.4:6380 172.21.0.4 6380 @ redis-sentinel 172.21.0.2 6379
1:X 05 Dec 2022 14:33:48.459 * +slave slave 172.21.0.3:6381 172.21.0.3 6381 @ redis-sentinel 172.21.0.2 6379
1:X 05 Dec 2022 14:33:50.508 * +sentinel sentinel 528e1f3ec17699f22eadcef4b3547558e6425565 172.21.0.7 26381 @ redis-sentinel 172.21.0.2 6379
1:X 05 Dec 2022 14:33:50.515 * +sentinel sentinel b828a2a8e11c71b5ce8b519eab7613286617b0d6 172.21.0.6 26380 @ redis-sentinel 172.21.0.2 6379
1:X 05 Dec 2022 14:38:10.248 # Failed to resolve hostname 'redis-master'
1:X 05 Dec 2022 14:38:14.246 # +sdown master redis-sentinel 172.21.0.2 6379
1:X 05 Dec 2022 14:38:14.392 # +new-epoch 1
1:X 05 Dec 2022 14:38:14.398 # +vote-for-leader 528e1f3ec17699f22eadcef4b3547558e6425565 1
1:X 05 Dec 2022 14:38:15.364 # +odown master redis-sentinel 172.21.0.2 6379 #quorum 3/2
1:X 05 Dec 2022 14:38:15.364 # Next failover delay: I will not start a failover before Mon Dec 5 14:38:25 2022
1:X 05 Dec 2022 14:38:15.513 # +config-update-from sentinel 528e1f3ec17699f22eadcef4b3547558e6425565 172.21.0.7 26381 @ redis-sentinel 172.21.0.2 6379
1:X 05 Dec 2022 14:38:15.513 # +switch-master redis-sentinel 172.21.0.2 6379 172.21.0.3 6381
1:X 05 Dec 2022 14:38:15.518 * +slave slave 172.21.0.4:6380 172.21.0.4 6380 @ redis-sentinel 172.21.0.3 6381
1:X 05 Dec 2022 14:38:15.525 # Failed to resolve hostname 'redis-master'
1:X 05 Dec 2022 14:38:15.525 * +slave slave :6379 6379 @ redis-sentinel 172.21.0.3 6381
1:X 05 Dec 2022 14:38:15.589 # Failed to resolve hostname 'redis-master'
1:X 05 Dec 2022 14:38:16.593 # Failed to resolve hostname 'redis-master'
1:X 05 Dec 2022 14:38:17.617 # Failed to resolve hostname 'redis-master'
1:X 05 Dec 2022 14:38:18.624 # Failed to resolve hostname 'redis-master'
1:X 05 Dec 2022 14:38:19.639 # Failed to resolve hostname 'redis-master'
1:X 05 Dec 2022 14:38:20.555 # +sdown slave :6379 6379 @ redis-sentinel 172.21.0.3 6381
sentinel在监测到主Redis宕机之后,通过选举,将一个从Redis选定为新的主Redis。通过查看sentinel日志可以发现,选定redis-slave-2(6381)为新的主Redis,同时将另外两个Redis作为从Redis。
注意:选定redis-slave-2为主Redis后,所有的配置文件都会被修改,主要是重新建立主从关系。
由于redis-master服务已经关掉,所以虽然sentinel将redis-master作为redis-slave-2的从服务,但是没有真正的建立。
此时需要重新启动redis-master服务,sentinel会重新建立一次主从关系
[root@localhost redis-sentinel]# docker-compose start redis-master
12、再次查询主从状态
[root@localhost redis-sentinel]# docker exec -it redis-slave-2 redis-cli -p 6381
127.0.0.1:6381> auth 123456
OK
127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.21.0.4,port=6380,state=online,offset=212612,lag=0
slave1:ip=172.21.0.2,port=6379,state=online,offset=212330,lag=1
master_failover_state:no-failover
master_replid:1d3a4d26003edee57495015d494849316aafb99d
master_replid2:cf03aa830887e4d5d132944bc1728f0086859e71
master_repl_offset:212612
second_repl_offset:54161
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:212612
从结果可以看出,redis-master启动后会重新建立主从关系,sentinel配置文件也会同步更新。
13、Sentinel的工作原理总结
1)每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他Sentinel实例发送一个 PING 命令。
2)如果一个实例(instance)距离最后一次有效回复PING命令的时间超过 down-after-milliseconds选项所指定的值,则这个实例会被Sentinel标记为主观下线。
3)如果一个Master被标记为主观下线,则正在监视这个Master的所有Sentinel要以每秒一次的频率确认Master的确进入了主观下线状态。
4)当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态,则Master会被标记为客观下线 。
5)在一般情况下,每个Sentinel会以每10秒一次的频率向它已知的所有Master,Slave发送INFO命令 。
6)当Master被Sentinel标记为客观下线时,Sentinel向下线的Master的所有Slave发送INFO命令的频率会从10秒一次改为每秒一次 。
7)若没有足够数量的Sentinel同意Master已经下线,Master的客观下线状态就会被移除。
若Master重新向Sentinel的PING命令返回有效回复,Master的主观下线状态就会被移除。
至此,docker-compose部署Redis-Sentinel集群完毕。
若文章图片、下载链接等信息出错,请在评论区留言反馈,博主将第一时间更新!如本文“对您有用”,欢迎随意打赏,谢谢!
评论