02 . Redis哨兵
Redis高可用概述
在
Web
服务器中,高可用 是指服务器可以 正常访问 的时间,衡量的标准是在 多长时间 内可以提供正常服务(99.9%
、99.99%
、99.999%
等等)。在Redis
层面,高可用 的含义要宽泛一些,除了保证提供 正常服务(如 主从分离、快速容灾技术 等),还需要考虑 数据容量扩展、数据安全 等等。在
Redis
中,实现 高可用 的技术主要包括 持久化、复制、哨兵 和 集群,下面简单说明它们的作用,以及解决了什么样的问题:持久化:持久化是 最简单的 高可用方法。它的主要作用是 数据备份,即将数据存储在 硬盘,保证数据不会因进程退出而丢失。
复制:复制是高可用
Redis
的基础,哨兵 和 集群 都是在 复制基础 上实现高可用的。复制主要实现了数据的多机备份以及对于读操作的负载均衡和简单的故障恢复。缺陷是故障恢复无法自动化、写操作无法负载均衡、存储能力受到单机的限制。哨兵:在复制的基础上,哨兵实现了 自动化 的 故障恢复。缺陷是 写操作 无法 负载均衡,存储能力 受到 单机 的限制。
集群:通过集群,
Redis
解决了 写操作 无法 负载均衡 以及 存储能力 受到 单机限制 的问题,实现了较为 完善 的 高可用方案。
Redis Sentinel的基本概念
Redis Sentinel
是Redis
高可用 的实现方案。Sentinel
是一个管理多个Redis
实例的工具,它可以实现对Redis
的 监控、通知、自动故障转移。下面先对Redis Sentinel
的 基本概念 进行简单的介绍。
基本名词说明:
基本名词 | 逻辑结构 | 物理结构 |
---|---|---|
Redis数据节点 | 主节点和从节点 | 主节点和从节点的进程 |
主节点(master) | Redis主数据库 | 一个独立的Redis进程 |
从节点(slave) | Redis从数据库 | 一个独立的Redis进程 |
Sentinel节点 | 监控Redis数据节点 | 一个独立的Sentinel进程 |
Sentinel节点集合 | 若干Sentinel节点的抽象组合 | 若干Sentinel节点进程 |
Redis Sentinel | Redis高可用实现方案 | Sentinel节点集合和Redis数据节点进程 |
应用客户端 | 泛指一个或多个客户端 | 一个或者多个客户端进程或者线程 |
如图所示,
Redis的 **主从复制模式** 和
Sentinel **高可用架构** 的示意图:
Redis主从复制的问题
Redis
主从复制 可将 主节点 数据同步给 从节点,从节点此时有两个作用:
# 1. 一旦主节点宕机,从节点作为主节点的备份可以随时顶上来。
# 2. 扩展主节点的读能力,分担主节点读压力。
**主从复制** 同时存在以下几个问题:
# 1. 一旦主节点宕机,从节点晋升成主节点,同时需要修改应用方的主节点地址,还需要命令所有 从节点去复制新的主节点,整个过程需要人工干预。
# 2. 主节点的写能力受到单机的限制。
# 3. 主节点的存储能力受到单机的限制。
# 4. 原生复制的弊端在早期的版本中也会比较突出,比如:Redis复制中断后,从节点会发起 `psync`。此时如果同步不成功,则会进行全量同步,主库执行 全量备份的同时,可能会造成毫秒或秒级的卡顿。
Redis Sentinel深入探究
Redis Sentinel的架构
Redis Sentinel的主要功能
Sentinel
的主要功能包括 主节点存活检测、主从运行情况检测、自动故障转移 (failover
)、主从切换。Redis
的Sentinel
最小配置是 一主一从。
Redis
的Sentinel
系统可以用来管理多个Redis
服务器,该系统可以执行以下四个任务:
监控
Sentinel
会不断的检查 主服务器 和 从服务器 是否正常运行。
通知
当被监控的某个
Redis
服务器出现问题,Sentinel
通过API
脚本 向 管理员 或者其他的 应用程序 发送通知。
自动故障转移
当 主节点 不能正常工作时,
Sentinel
会开始一次 自动的 故障转移操作,它会将与 失效主节点 是 主从关系 的其中一个 从节点 升级为新的 主节点,并且将其他的 从节点 指向 新的主节点。
配置提供者
在
Redis Sentinel
模式下,客户端应用 在初始化时连接的是Sentinel
节点集合,从中获取 主节点 的信息。
主观下线和客观下线
默认情况下,每个
Sentinel
节点会以 每秒一次 的频率对Redis
节点和 其它 的Sentinel
节点发送PING
命令,并通过节点的 回复 来判断节点是否在线。
主观下线
主观下线 适用于所有 主节点 和 从节点。如果在
down-after-milliseconds
毫秒内,Sentinel
没有收到 目标节点 的有效回复,则会判定 该节点 为 主观下线。
客观下线
客观下线 只适用于 主节点。如果 主节点 出现故障,
Sentinel
节点会通过sentinel is-master-down-by-addr
命令,向其它Sentinel
节点询问对该节点的 状态判断。如果超过<quorum>
个数的节点判定 主节点 不可达,则该Sentinel
节点会判断 主节点 为 客观下线。
Sentinel的通信命令
Sentinel
节点连接一个Redis
实例的时候,会创建cmd
和pub/sub
两个 连接。Sentinel
通过cmd
连接给Redis
发送命令,通过pub/sub
连接到Redis
实例上的其他Sentinel
实例。
Sentinel
与Redis
主节点 和 从节点 交互的命令,主要包括:
命令 | 作 用 |
---|---|
PING | Sentinel 向 Redis 节点发送 PING 命令,检查节点的状态 |
INFO | Sentinel 向 Redis 节点发送 INFO 命令,获取它的 从节点信息 |
PUBLISH | Sentinel 向其监控的 Redis 节点 __sentinel__:hello 这个 channel 发布 自己的信息 及 主节点 相关的配置 |
SUBSCRIBE | Sentinel 通过订阅 Redis 主节点 和 从节点 的 __sentinel__:hello 这个 channnel ,获取正在监控相同服务的其他 Sentinel 节点 |
Sentinel与Sentinel交互的命令,主要包括:
命令 | 作 用 |
---|---|
PING | Sentinel 向其他 Sentinel 节点发送 PING 命令,检查节点的状态 |
SENTINEL:is-master-down-by-addr | 和其他 Sentinel 协商 主节点 的状态,如果 主节点 处于 SDOWN 状态,则投票自动选出新的 主节点 |
Redis Sentinel的工作原理
每个
Sentinel 节点都需要定期执行以下任务:
- 每个
Sentinel
以 每秒钟 一次的频率,向它所知的 主服务器、从服务器 以及其他Sentinel
实例 发送一个PING
命令。
1 . 每个Sentinel 以每秒钟一次频率,向他所知的主服务器、从服务器以及其他Sentinel实例发送一个PING命令。
2 . 如果一个 实例(
instance
)距离 最后一次 有效回复PING
命令的时间超过down-after-milliseconds
所指定的值,那么这个实例会被Sentinel
标记为 主观下线。
3 . 如果一个 主服务器 被标记为 主观下线,那么正在 监视 这个 主服务器 的所有
Sentinel
节点,要以 每秒一次 的频率确认 主服务器 的确进入了 主观下线 状态。
4 . 如果一个 主服务器 被标记为 主观下线,并且有 足够数量 的
Sentinel
(至少要达到 配置文件 指定的数量)在指定的 时间范围 内同意这一判断,那么这个 主服务器 被标记为 客观下线。
5 . 在一般情况下, 每个
Sentinel
会以每10
秒一次的频率,向它已知的所有 主服务器 和 从服务器 发送INFO
命令。当一个 主服务器 被Sentinel
标记为 客观下线 时,Sentinel
向 下线主服务器 的所有 从服务器 发送INFO
命令的频率,会从10
秒一次改为 每秒一次。
6 . Sentinel
和其他
Sentinel协商 主节点 的状态,如果 **主节点** 处于
SDOWN` 状态,则投票自动选出新的 主节点。将剩余的 从节点 指向 新的主节点 进行 数据复制。
- 当没有足够数量的
Sentinel
同意 主服务器 下线时, 主服务器 的 客观下线状态 就会被移除。当 主服务器 重新向Sentinel
的PING
命令返回 有效回复 时,主服务器 的 主观下线状态 就会被移除。
注意:一个有效的
PING 回复可以是:
+PONG、
-LOADING或者
-MASTERDOWN。如果服务器返回除以上三种回复之外的其他回复,又或者在指定时间内没有回复
PING命令, 那么
Sentinel 认为服务器返回的回复无效(
non-valid)。
Redis Sentinel搭建
环境清单
节点名(角色名) | IP地址 | 端口号 | 硬件 | 网络 |
---|---|---|---|---|
Redis Master | 192.168.171.136 | 16379 | 2C4G | Nat,内网 |
Redis Slave1 | 192.168.171.137 | 26379 | 2C4G | Nat,内网 |
Redis Slave2 | 192.168.171.138 | 36379 | 2C4G | Nat,内网 |
Redis Sentinel1 | 192.168.171.136 | 16380 | 2C4G | Nat,内网 |
Redis Sentinel2 | 192.168.171.137 | 26380 | 2C4G | Nat,内网 |
Redis Sentinel3 | 192.168.171.138 | 36380 | 2C4G | Nat,内网 |
注意事项
# 1. 一个稳健的 `Redis Sentinel` 集群,应该使用至少三个`Sentinel` 实例,并且保证讲这些实例放到不同的机器上,甚至不同的物理区域。
# 2. Sentinel无法保证强一致性。
# 3. 常见的客户端应用库都支持 `Sentinel`。
# 4. Sentinel需要通过不断的测试和观察,才能保证高可用。
Redis Sentinel的配置文件
# 哨兵sentinel实例运行的端口,默认26379
port 26379
# 哨兵sentinel的工作目录
dir ./
# 哨兵sentinel监控的redis主节点的
## ip:主机ip地址
## port:哨兵端口号
## master-name:可以自己命名的主节点名字(只能由字母A-z、数字0-9 、这三个字符".-_"组成。)
## quorum:当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
# 当在Redis实例中开启了requirepass <foobared>,所有连接Redis实例的客户端都要提供密码。
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster 123456
# 指定主节点应答哨兵sentinel的最大时间间隔,超过这个时间,哨兵主观上认为主节点下线,默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# 指定了在发生failover主备切换时,最多可以有多少个slave同时对新的master进行同步。这个数字越小,完成failover所需的时间就越长;反之,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为1,来保证每次只有一个slave,处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
# 故障转移的超时时间failover-timeout,默认三分钟,可以用在以下这些方面:
# 1. 同一个sentinel对同一个master两次failover之间的间隔时间。
# 2. 当一个slave从一个错误的master那里同步数据时开始,直到slave被纠正为从正确的master那里同步数据时结束。
# 3. 当想要取消一个正在进行的failover时所需要的时间。
# 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来同步数据了
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
# 当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本。一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
# 对于脚本的运行结果有以下规则:
# 1. 若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10。
# 2. 若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
# 3. 如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
安装Redis
三台机器都要安装
yum -y install gcc
wget http://download.redis.io/releases/redis-4.0.14.tar.gz
tar xvf redis-4.0.14.tar.gz -C /opt/
cd /opt/redis-4.0.14
# Redis的编译,只将命令文件编译,将会在当前目录生成bin目录
make && make install PREFIX=/usr/local/redis
cd ..
mv redis-4.0.14 /usr/local/redis
# 创建环境变量
echo 'PATH=$PATH:/usr/local/redis/src/' >> /etc/profile
source /etc/profile
# 此时在任何目录位置都可以是用redis-server等相关命令
[root@redis1 ~]# redis-
redis-benchmark redis-check-rdb redis-sentinel redis-trib.rb
redis-check-aof redis-cli redis-server
Redis-Server的配置管理
分别拷贝三份
redis.conf
文件到/usr/local/redis-sentinel
目录下面。三个配置文件分别对应master
、slave1
和slave2
三个Redis
节点的 启动配置。
mkdir /usr/local/redis-sentinel/
mkdir /usr/local/redis/backup
sudo cp /usr/local/redis/redis.conf /usr/local/redis-sentinel/redis-16379.conf
sudo cp /usr/local/redis/redis.conf /usr/local/redis-sentinel/redis-26379.conf
sudo cp /usr/local/redis/redis.conf /usr/local/redis-sentinel/redis-36379.conf
分别修改三份配置文件如下
主节点:redis-16379.conf
daemonize yes
pidfile /var/run/redis-16379.pid
logfile /var/log/redis-16379.log
port 16379
bind 0.0.0.0
timeout 300
databases 16
dbfilename dump-16379.db
dir /usr/local/redis/backup
masterauth 123456
requirepass 123456
从节点1:redis-26379.conf
daemonize yes
pidfile /var/run/redis-26379.pid
logfile /var/log/redis-26379.log
port 26379
bind 0.0.0.0
timeout 300
databases 16
dbfilename dump-26379.db
dir /usr/local/redis/backup
masterauth 123456
requirepass 123456
slaveof 192.168.171.136 16379
从节点2:redis-36379.conf
daemonize yes
pidfile /var/run/redis-36379.pid
logfile /var/log/redis/redis-36379.log
port 36379
bind 0.0.0.0
timeout 300
databases 16
dbfilename dump-36379.db
dir ./redis-workdir
masterauth 123456
requirepass 123456
slaveof 192.168.171.136 16379
注意
如果要做 自动故障转移,建议所有的
redis.conf
都设置masterauth
。因为 自动故障 只会重写 主从关系,即slaveof
,不会自动写入masterauth
。如果Redis
原本没有设置密码,则可以忽略。
Redis-Server启动验证
按顺序分别启动
16379
,26379
和36379
三个Redis
节点,启动命令和启动日志如下:
Redis
的启动命令:
sudo redis-server /usr/local/redis-sentinel/redis-16379.conf
sudo redis-server /usr/local/redis-sentinel/redis-26379.conf
sudo redis-server /usr/local/redis-sentinel/redis-36379.conf
[root@redis-master ~]# redis-cli -h 127.0.0.1 -p 16379 -a 123456
Warning: Using a password with '-a' option on the command line interface may not be safe.
127.0.0.1:16379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.171.137,port=26379,state=online,offset=70,lag=1
slave1:ip=192.168.171.138,port=36379,state=online,offset=70,lag=0
master_replid:15979cfdbb2ff2a9a95ce8b2a37c4779d299dfc2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:70
查看 Redis
的启动日志:
- 节点
redis-16379
2364:M 09 May 18:26:44.327 * Starting BGSAVE for SYNC with target: disk
2364:M 09 May 18:26:44.327 * Background saving started by pid 2368
2368:C 09 May 18:26:44.328 * DB saved on disk
2368:C 09 May 18:26:44.329 * RDB: 6 MB of memory used by copy-on-write
2364:M 09 May 18:26:44.332 * Background saving terminated with success
2364:M 09 May 18:26:44.332 * Synchronization with slave 192.168.171.137:26379 succeeded
2364:M 09 May 18:27:03.280 * Slave 192.168.171.138:36379 asks for synchronization
2364:M 09 May 18:27:03.280 * Partial resynchronization not accepted: Replication ID mismatch (Slave asked for '4f408b9c0c3713dd6328d9887d48538ba322105a', my replication IDs are '15979cfdbb2ff2a9a95ce8b2a37c4779d299dfc2' and '0000000000000000000000000000000000000000')
2364:M 09 May 18:27:03.280 * Starting BGSAVE for SYNC with target: disk
2364:M 09 May 18:27:03.280 * Background saving started by pid 2369
2369:C 09 May 18:27:03.281 * DB saved on disk
2369:C 09 May 18:27:03.282 * RDB: 6 MB of memory used by copy-on-write
2364:M 09 May 18:27:03.303 * Background saving terminated with success
2364:M 09 May 18:27:03.304 * Synchronization with slave 192.168.171.138:36379 succeeded
以下两行日志日志表明,redis-16379作为Redis的主节点,redis-26379和 redis-36379作为从节点,从主节点同步数据。
2369:C 09 May 18:27:03.282 * RDB: 6 MB of memory used by copy-on-write
2364:M 09 May 18:27:03.303 * Background saving terminated with success
2364:M 09 May 18:27:03.304 * Synchronization with slave 192.168.171.138:36379 succeeded
- 节点
redis-26379
cat /var/log/redis-26379.log
2388:S 09 May 18:26:44.370 * Ready to accept connections
2388:S 09 May 18:26:44.370 * Connecting to MASTER 192.168.171.136:16379
2388:S 09 May 18:26:44.370 * MASTER <-> SLAVE sync started
2388:S 09 May 18:26:44.370 * Non blocking connect for SYNC fired the event.
2388:S 09 May 18:26:44.371 * Master replied to PING, replication can continue...
2388:S 09 May 18:26:44.371 * Trying a partial resynchronization (request 4f408b9c0c3713dd6328d9887d48538ba322105a:1).
2388:S 09 May 18:26:44.372 * Full resync from master: 15979cfdbb2ff2a9a95ce8b2a37c4779d299dfc2:0
2388:S 09 May 18:26:44.372 * Discarding previously cached master state.
2388:S 09 May 18:26:44.377 * MASTER <-> SLAVE sync: receiving 176 bytes from master
2388:S 09 May 18:26:44.377 * MASTER <-> SLAVE sync: Flushing old data
2388:S 09 May 18:26:44.377 * MASTER <-> SLAVE sync: Loading DB in memory
2388:S 09 May 18:26:44.377 * MASTER <-> SLAVE sync: Finished with success
- 节点
redis-36379
cat /var/log/redis-36379.log
5623:S 09 May 18:27:03.321 * Trying a partial resynchronization (request 4f408b9c0c3713dd6328d9887d48538ba322105a:1).
5623:S 09 May 18:27:03.322 * Full resync from master: 15979cfdbb2ff2a9a95ce8b2a37c4779d299dfc2:28
5623:S 09 May 18:27:03.322 * Discarding previously cached master state.
5623:S 09 May 18:27:03.345 * MASTER <-> SLAVE sync: receiving 176 bytes from master
5623:S 09 May 18:27:03.345 * MASTER <-> SLAVE sync: Flushing old data
5623:S 09 May 18:27:03.345 * MASTER <-> SLAVE sync: Loading DB in memory
5623:S 09 May 18:27:03.346 * MASTER <-> SLAVE sync: Finished with success
Sentinel的配置管理
分别拷贝三份
redis-sentinel.conf
文件到/usr/local/redis-sentinel
目录下面。三个配置文件分别对应master
、slave1
和slave2
三个Redis
节点的 哨兵配置。
sudo cp /usr/local/redis/sentinel.conf /usr/local/redis-sentinel/sentinel-16380.conf
sudo cp /usr/local/redis/sentinel.conf /usr/local/redis-sentinel/sentinel-26380.conf
sudo cp /usr/local/redis/sentinel.conf /usr/local/redis-sentinel/sentinel-36380.conf
节点1:sentinel-16380.conf
bind 0.0.0.0
port 16380
daemonize yes
dir /usr/local/redis/backup
logfile "sentinel-16380.log"
sentinel monitor master 192.168.171.136 16379 2
sentinel down-after-milliseconds master 30000
sentinel parallel-syncs master 1
sentinel failover-timeout master 180000
sentinel deny-scripts-reconfig yes
sentinel auth-pass master 123456
节点2:sentinel-26380.conf
bind 0.0.0.0
port 26380
daemonize yes
dir /usr/local/redis/backup
logfile "sentinel-26380.log"
sentinel monitor master 192.168.171.136 16379 2
sentinel down-after-milliseconds master 30000
sentinel parallel-syncs master 1
sentinel failover-timeout master 180000
sentinel deny-scripts-reconfig yes
sentinel auth-pass master 123456
节点3:sentinel-36380.conf
bind 0.0.0.0
port 36380
daemonize yes
dir /usr/local/redis/backup
logfile "sentinel-36380.log"
sentinel monitor master 192.168.171.136 16379 2
sentinel down-after-milliseconds master 30000
sentinel parallel-syncs master 1
sentinel failover-timeout master 180000
sentinel deny-scripts-reconfig yes
sentinel auth-pass master 123456
Sentinel启动验证
按顺序分别启动
16380,
26380和
36380三个
Sentinel 节点,启动命令和启动日志如下:
# sudo redis-sentinel /usr/local/redis-sentinel/sentinel-16380.conf
# sudo redis-sentinel /usr/local/redis-sentinel/sentinel-26380.conf
# sudo redis-sentinel /usr/local/redis-sentinel/sentinel-36380.conf
# 记得挨个查看端口进程喔
[root@redis-master ~]# lsof -i:16380
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
redis-sen 2062 root 6u IPv4 37369 0t0 TCP *:16380 (LISTEN)
[root@redis-master ~]# ps aux |grep sentinel
root 2062 0.1 0.3 145420 7712 ? Rsl 17:45 0:00 redis-sentinel 0.0.0.0:16380 [sentinel]
查看
Sentinel 的启动日志:
节点
sentinel-16380`
cat /usr/local/redis/backup/sentinel-26380.log
4586:X 09 May 22:34:43.499 # Configuration loaded
4587:X 09 May 22:34:43.501 * Running mode=sentinel, port=26380.
4587:X 09 May 22:34:43.501 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
4587:X 09 May 22:34:43.502 # Sentinel ID is 94c9b3deb09ebf98708ec5d0df56457198adbbe1
4587:X 09 May 22:34:43.502 # +monitor master master 127.0.0.1 6379 quorum 2
4587:X 09 May 22:34:43.502 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ master 127.0.0.1 6379
4587:X 09 May 22:34:43.503 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ master 127.0.0.1 6379
4587:X 09 May 22:34:43.504 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ master 127.0.0.1 6379
4587:X 09 May 22:37:26.881 * +sentinel sentinel 6f85655e82ba92d709f2e59b6cb4b22d91302501 127.0.0.1 26381 @ master 127.0.0.1 6379
4587:X 09 May 22:37:32.121 * +sentinel sentinel 3b2ad68e2f8f6a2e19132a1eabb95ea099eef525 127.0.0.1 26382 @ master 127.0.0.1 6379
sentinel-16380节点的 Sentinel ID 为 69d05b86a82102a8919231fd3c2d1f21ce86e000,并通过 Sentinel ID 把自身加入 sentinel 集群中
节点
sentinel-26380`
cat /usr/local/redis/backup/sentinel-26380.log
4231:X 09 May 22:25:59.504 # User requested shutdown...
4231:X 09 May 22:25:59.504 * Removing the pid file.
4231:X 09 May 22:25:59.504 # Sentinel is now ready to exit, bye bye...
4586:X 09 May 22:34:43.499 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
4586:X 09 May 22:34:43.499 # Redis version=4.0.14, bits=64, commit=00000000, modified=0, pid=4586, just started
4586:X 09 May 22:34:43.499 # Configuration loaded
4587:X 09 May 22:34:43.501 * Running mode=sentinel, port=26380.
4587:X 09 May 22:34:43.501 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
4587:X 09 May 22:34:43.502 # Sentinel ID is 94c9b3deb09ebf98708ec5d0df56457198adbbe1
4587:X 09 May 22:34:43.502 # +monitor master master 127.0.0.1 6379 quorum 2
4587:X 09 May 22:34:43.502 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ master 127.0.0.1 6379
4587:X 09 May 22:34:43.503 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ master 127.0.0.1 6379
4587:X 09 May 22:34:43.504 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ master 127.0.0.1 6379
4587:X 09 May 22:37:26.881 * +sentinel sentinel 6f85655e82ba92d709f2e59b6cb4b22d91302501 127.0.0.1 26381 @ master 127.0.0.1 6379
4587:X 09 May 22:37:32.121 * +sentinel sentinel 3b2ad68e2f8f6a2e19132a1eabb95ea099eef525 127.0.0.1 26382 @ master 127.0.0.1 6379
sentinel-26380
节点的 Sentinel ID
为 21e30244cda6a3d3f55200bcd904d0877574e506
,并通过 Sentinel ID
把自身加入 sentinel集群中。此时
sentinel集群中已有
sentinel-16380和
sentinel-26380 两个节点
节点
sentinel-36380`
cat /usr/local/redis/backup/sentinel-26381.log
4719:X 09 May 22:37:24.813 # Configuration loaded
4720:X 09 May 22:37:24.815 * Running mode=sentinel, port=26381.
4720:X 09 May 22:37:24.815 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
4720:X 09 May 22:37:24.815 # Sentinel ID is 6f85655e82ba92d709f2e59b6cb4b22d91302501
4720:X 09 May 22:37:24.815 # +monitor master master 127.0.0.1 6379 quorum 2
4720:X 09 May 22:37:24.815 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ master 127.0.0.1 6379
4720:X 09 May 22:37:24.816 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ master 127.0.0.1 6379
4720:X 09 May 22:37:24.816 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ master 127.0.0.1 6379
4720:X 09 May 22:37:26.497 * +sentinel sentinel 94c9b3deb09ebf98708ec5d0df56457198adbbe1 127.0.0.1 26380 @ master 127.0.0.1 6379
4720:X 09 May 22:37:32.121 * +sentinel sentinel 3b2ad68e2f8f6a2e19132a1eabb95ea099eef525 127.0.0.1 26382 @ master 127.0.0.1 6379
sentinel-36380
节点的 Sentinel ID
为 fd166dc66425dc1d9e2670e1f17cb94fe05f5fc7
,并通过 Sentinel ID
把自身加入 sentinel
集群中。此时 sentinel
集群中已有 sentinel-16380
,sentinel-26380
和 sentinel-36380 三个节点
Sentinel配置刷新
- 节点1:sentinel-16380.conf
sentinel-16380.conf
文件新生成如下的配置项:
bind 0.0.0.0
port 16380
daemonize yes
dir "/usr/local/redis/backup"
logfile "sentinel-16380.log"
sentinel myid cf91bc0b7c1d9138e7d654f025b813e48cb40bfc
sentinel deny-scripts-reconfig yes
sentinel monitor master 192.168.171.136 16379 2
sentinel auth-pass master 123456
sentinel config-epoch master 0
sentinel leader-epoch master 0
# Generated by CONFIG REWRITE
sentinel known-slave master 192.168.171.138 36379
sentinel known-slave master 192.168.171.137 26379
sentinel known-sentinel master 192.168.171.138 36380 13402e25e40f318f4bf1eab432fedd7c504ee64b
sentinel known-sentinel master 192.168.171.137 26380 6c5507ed7919e5935301afe0a2c362e6f0d6bb40
sentinel current-epoch 0
可以注意到,
sentinel-16380.conf
刷新写入了Redis
主节点关联的所有 从节点redis-26379
和redis-36379
,同时写入了其余两个Sentinel
节点sentinel-26380
和sentinel-36380
的IP
地址,端口号 和Sentinel ID
。
bind 0.0.0.0
port 26380
daemonize yes
dir "/usr/local/redis/backup"
logfile "sentinel-26380.log"
sentinel myid 6c5507ed7919e5935301afe0a2c362e6f0d6bb40
sentinel deny-scripts-reconfig yes
sentinel monitor master 192.168.171.136 16379 2
sentinel auth-pass master 123456
sentinel config-epoch master 0
sentinel leader-epoch master 0
# Generated by CONFIG REWRITE
sentinel known-slave master 192.168.171.137 26379
sentinel known-slave master 192.168.171.138 36379
sentinel known-sentinel master 192.168.171.136 16380 cf91bc0b7c1d9138e7d654f025b813e48cb40bfc
sentinel known-sentinel master 192.168.171.138 36380 13402e25e40f318f4bf1eab432fedd7c504ee64b
sentinel current-epoch 0
可以注意到,
sentinel-26380.conf
刷新写入了Redis
主节点关联的所有 从节点redis-26379
和redis-36379
,同时写入了其余两个Sentinel
节点sentinel-36380
和sentinel-16380
的IP
地址,端口号 和Sentinel ID
。
bind 0.0.0.0
port 36380
daemonize yes
dir "/usr/local/redis/backup"
logfile "sentinel-36380.log"
sentinel myid 13402e25e40f318f4bf1eab432fedd7c504ee64b
sentinel deny-scripts-reconfig yes
sentinel monitor master 192.168.171.136 16379 2
sentinel auth-pass master 123456
sentinel config-epoch master 0
sentinel leader-epoch master 0
# Generated by CONFIG REWRITE
sentinel known-slave master 192.168.171.137 26379
sentinel known-slave master 192.168.171.138 36379
sentinel known-sentinel master 192.168.171.137 26380 6c5507ed7919e5935301afe0a2c362e6f0d6bb40
sentinel known-sentinel master 192.168.171.136 16380 cf91bc0b7c1d9138e7d654f025b813e48cb40bfc
sentinel current-epoch 0
可以注意到,
sentinel-36380.conf
刷新写入了Redis
主节点关联的所有 从节点redis-26379
和redis-36379
,同时写入了其余两个Sentinel
节点sentinel-16380
和sentinel-26380
的IP
地址,端口号 和Sentinel ID
。
Sentinel时客户端命令
检查其他
Sentinel节点的状态,返回
PONG 为正常。
PING sentinel
显示被监控的所有主节点以及它们的状态
SENTINEL masters
显示指定主节点 的信息和状态
SENTINEL master master
显示指定主节点的所有从节点以及它们的状态
SENTINEL slaves <master_name>
返回指定 主节点 的 IP
地址和 端口。如果正在进行 failover
或者 failover
已经完成,将会显示被提升为 主节点 的 从节点 的 IP
地址和 端口。
SENTINEL get-master-addr-by-name <master_name>
重置名字匹配该正则表达式的所有的主节点的状态信息,清除它之前的状态信息,以及从节点的信息。
SENTINEL reset <pattern>
强制当前
Sentinel节点执行
failover,并且不需要得到其他
Sentinel节点的同意。但是
failover后会将最新的配置发送给其他
Sentinel 节点。
SENTINEL failover <master_name>
验证Sentinel状态
127.0.0.1:16380> INFO sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=master,status=ok,address=192.168.171.136:16379,slaves=2,sentinels=3
Redis Sentinel故障切换与恢复
我们尝试关闭6379这台实例主节点
redis-cli -h 127.0.0.1 -p 16379 -a 123456 # 连接到Redis主机
127.0.0.1:6379> shutdown # 终止Redis服务
# 有时候服务并没有宕机,可以直接kill掉,记得连接一下确认宕机没
接下来稍等3-5s,我们去登录一下哨兵,看一下主节点有没有迁移
[root@redis-slave1 redis-sentinel]# redis-cli -h 127.0.0.1 -p 26380 -a 123456
127.0.0.1:26380> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=master,status=ok,address=192.168.171.137:26379,slaves=2,sentinels=3
# 我们可以看到主节点已经换成192.168.171.137这一台节点了,之前是136节点
或者查看
Redis主从集群的主节点信息。可以发现
redis-26379 晋升为新的主节点。
redis-cli -h 127.0.0.1 -p 26380 -a 123456
127.0.0.1:26380> SENTINEL masters
1) 1) "name"
2) "master"
3) "ip"
4) "192.168.171.137"
5) "port"
6) "26379"
7) "runid"
8) "2d20ec05ba7c099ab2bcae4ee0a1bc2c441f9d77"
9) "flags"
10) "master"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "483"
19) "last-ping-reply"
20) "483"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "7239"
25) "role-reported"
26) "master"
27) "role-reported-time"
28) "78176"
29) "config-epoch"
30) "1"
31) "num-slaves"
32) "2"
33) "num-other-sentinels"
34) "2"
35) "quorum"
36) "2"
37) "failover-timeout"
38) "180000"
39) "parallel-syncs"
40) "1"
Redis Sentinel日志跟踪
查看任意 Sentinel
节点的日志如下:
1592:X 10 May 12:03:31.061 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1592:X 10 May 12:03:31.062 # Sentinel ID is 6c5507ed7919e5935301afe0a2c362e6f0d6bb40
1592:X 10 May 12:03:31.062 # +monitor master master 192.168.171.136 16379 quorum 2
1592:X 10 May 12:03:31.063 * +slave slave 192.168.171.137:26379 192.168.171.137 26379 @ master 192.168.171.136 16379
1592:X 10 May 12:03:31.064 * +slave slave 192.168.171.138:36379 192.168.171.138 36379 @ master 192.168.171.136 16379
1592:X 10 May 12:03:32.413 * +sentinel sentinel cf91bc0b7c1d9138e7d654f025b813e48cb40bfc 192.168.171.136 16380 @ master 192.168.171.136 16379
1592:X 10 May 12:04:02.703 * +sentinel sentinel 13402e25e40f318f4bf1eab432fedd7c504ee64b 192.168.171.138 36380 @ master 192.168.171.136 16379
1592:X 10 May 12:09:42.035 # +sdown sentinel cf91bc0b7c1d9138e7d654f025b813e48cb40bfc 192.168.171.136 16380 @ master 192.168.171.136 16379
1592:X 10 May 12:11:52.177 # +sdown master master 192.168.171.136 16379
1592:X 10 May 12:11:52.257 # +new-epoch 1
1592:X 10 May 12:11:52.258 # +vote-for-leader 13402e25e40f318f4bf1eab432fedd7c504ee64b 1
1592:X 10 May 12:11:53.275 # +odown master master 192.168.171.136 16379 #quorum 2/2
1592:X 10 May 12:11:53.275 # Next failover delay: I will not start a failover before Sun May 10 12:17:52 2020
1592:X 10 May 12:11:53.476 # +config-update-from sentinel 13402e25e40f318f4bf1eab432fedd7c504ee64b 192.168.171.138 36380 @ master 192.168.171.136 16379
1592:X 10 May 12:11:53.476 # +switch-master master 192.168.171.136 16379 192.168.171.137 26379
1592:X 10 May 12:11:53.476 * +slave slave 192.168.171.138:36379 192.168.171.138 36379 @ master 192.168.171.137 26379
1592:X 10 May 12:11:53.476 * +slave slave 192.168.171.136:16379 192.168.171.136 16379 @ master 192.168.171.137 26379
1592:X 10 May 12:12:23.504 # +sdown slave 192.168.171.136:16379 192.168.171.136 16379 @ master 192.168.171.137 26379
Redis的配置文件
分别查看三个 redis
节点的配置文件,发生 主从切换 时 redis.conf
的配置会自动发生刷新。
节点 redis-16379
[root@redis-master redis-sentinel]# cat redis-16379.conf
daemonize yes
pidfile /var/run/redis-16379.pid
logfile /var/log/redis-16379.log
port 16379
bind 0.0.0.0
timeout 300
databases 16
dbfilename dump-16379.db
dir /usr/local/redis/backup
masterauth 123456
requirepass 123456
- 节点 redis-26379
[root@redis-slave1 redis-sentinel]# cat redis-26379.conf
daemonize yes
pidfile "/var/run/redis-26379.pid"
logfile "/var/log/redis-26379.log"
port 26379
bind 0.0.0.0
timeout 300
databases 16
dbfilename "dump-26379.db"
dir "/usr/local/redis/backup"
masterauth "123456"
requirepass "123456"
- 节点 redis-36379
[root@redis-slave2 redis-sentinel]# cat redis-36379.conf
daemonize yes
pidfile "/var/run/redis-36379.pid"
logfile "/var/log/redis-36379.log"
port 36379
bind 0.0.0.0
timeout 300
databases 16
dbfilename "dump-36379.db"
dir "/usr/local/redis/backup"
masterauth "123456"
requirepass "123456"
slaveof 192.168.171.137 26379
分析:
redis-26379
节点slaveof
配置被移除,晋升为 主节点。redis-16379
节点处于 宕机状态。redis-36379
的slaveof
配置更新为127.0.0.1 redis-26379
,成为redis-26379
的 从节点。
重启节点 redis-16379
。待正常启动后,再次查看它的 redis.conf
文件,配置如下:
[root@redis-master redis-sentinel]# cat redis-16379.conf
daemonize yes
pidfile "/var/run/redis-16379.pid"
logfile "/var/log/redis-16379.log"
port 16379
bind 0.0.0.0
timeout 300
databases 16
dbfilename "dump-16379.db"
dir "/usr/local/redis/backup"
masterauth "123456"
requirepass "123456"
# Generated by CONFIG REWRITE
slaveof 192.168.171.137 26379
节点 redis-16379
的配置文件新增一行 slaveof
配置属性,指向 redis-26379
,即成为 新的主节点 的 从节点。
本文首先对 Redis
实现高可用的几种模式做出了阐述,指出了 Redis
主从复制 的不足之处,进一步引入了 Redis Sentinel
哨兵模式 的相关概念,深入说明了 Redis Sentinel
的 具体功能,基本原理,高可用搭建 和 自动故障切换 验证等。
当然,Redis Sentinel
仅仅解决了 高可用 的问题,对于 主节点 单点写入和单节点无法扩容等问题,还需要引入 Redis Cluster
集群模式 予以解决。