单哨兵模式

哨兵模式概述

为什么要启动哨兵模式

当我们的主服务器宕机后,要手动的去切换主从模式,这样的人工干预,费事费力,还会造成一段时间我们的服务不能使用。所有我们要使用哨兵模式来解决这一问题。

什么是哨兵模式

哨兵是对Redis的系统的运行情况的监控,它是一个独立进程,功能有二个:

监控主机Redis和从机Redis是否运行正常;

主机Redis出现故障后自动将从机转化为主机;

哨兵工作原理

单个哨兵的工作原理:

单个哨兵,只需要监控主Redis,就可能得到从Redis。

多个哨兵的工作原理:

多个哨兵,不仅同时监控主从Redis,而且哨兵之间互为监控。多个哨兵,不仅同时监控主从Redis,而且哨兵之间互为监控。

多个哨兵,防止哨兵单点故障。

哨兵功能

集群监控:负责监控主从集群中的Master和Slave进程是否正常工作。

故障转移(failover):如果Master宕机,会自动从Slave中选举出新的Master,进行主从自动切换。

配置中心:如果发生了故障转移,Sentinel负责通知客户端新的Master的地址。

消息通知:如果某个redis节点有故障,那么Sentsinel会发送报警消息给系统管理员。

配置参数说明

 # 关闭保护模式,使外网能访问。
 protected-mode no
 ​
 # 修改端口,三份文件分别不同。
 port 26379
 ​
 # 修改为后台运行。
 daemonize yes
 ​
 # 指定不同pid文件,注意文件夹不存在自己要新建。
 pidfile /var/run/redis-sentinel.pid
 ​
 # 配置哨兵日志文件。
 logfile ""
 ​
 # 配置哨兵工作路径。
 dir "/tmp"
 ​
 # 配置哨兵需要监控的主节点ip和端口,2表示哨兵数(quorum)
 sentinel monitor mymaster 127.0.0.1 6379 2
 ​
 # 配置哨兵连接主节点的认证密码。(主节点配置的requirepass)。
 sentinel auth-pass mymaster 123
 ​
 # 配置多少毫秒后没收到主节点的反馈,则主观认为主节点down了。
 sentinel down-after-milliseconds mymaster 5000
 ​
 # 表示如果30秒后,mysater仍没活过来,则启动failover,从剩下的slave中选一个升级为master
 sentinel failover-timeout mymaster 30000
 ​
 # parallel-syncs 指定了在执行故障转移时,最多可以有多少个slave同时对新的master进行同步,这个数字越小,完成故障转移所需的时间
 sentinel parallel-syncs mymaster 1

注意:

majority表示大多数哨兵

quorum表示哨兵数

如果quorum < majority,比如5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵授权就可以执行切换。

但是如果quorum >= majority,那么必须quorum数量的哨兵都授权,比如5个哨兵,quorum是5,那么必须5个哨兵都同意授权,才能执行切换。

单哨兵模式

在一主多从的环境中,Redis-1为主机,Redis-2、Redis-3为从机,哨兵主机Redis-0

设置哨兵

 # 配置哨兵文件
 cd /usr/local/src/redis-6.2.14
 ​
 # 过滤并生成精简配置文件
 grep -E -v "^$|^#" sentinel.conf > /usr/local/redis/etc/sentinel.conf
 ​
 # 切换目录
 cd  /usr/local/redis/etc/
 ​
 # 修改哨兵配置文件
 vim sentinel.conf
 ​
 # 修改配置内容(修改原因名字变动Redis1)
 sentinel monitor Redis1 192.168.7.71 6379 1
 sentinel down-after-milliseconds Redis1 30000
 sentinel parallel-syncs Redis1 1
 sentinel failover-timeout Redis1 180000
 ​
 # 配置内容如果设置了密码需要添加
 sentinel auth-pass Redis1 123456
 ​
 # 配置内容后台运行
 daemonize yes
 ​
 # 配置内容哨兵日志文件
 logfile "/var/log/redis/sentinel.log"
 ​
 # 创建日志文件
 mkdir -p /var/log/redis
 ​
 ​
 # 可直接使用模板
 port 26379
 daemonize yes
 pidfile "/var/run/redis-sentinel.pid"
 logfile "/var/log/redis/sentinel.log"
 dir "/tmp"
 protected-mode no
 ​
 sentinel monitor Redis1 192.168.7.71 6379 1
 sentinel auth-pass Redis1 123456
 sentinel down-after-milliseconds Redis1 30000
 sentinel failover-timeout Redis1 180000
 sentinel parallel-syncs Redis1 1
 ​
 sentinel resolve-hostnames no
 sentinel announce-hostnames no
 ​
 ​
 # 注意:
 mymaster:监控主数据的名称,命名时可以使用大小写字母和“.-_”符号
 192.168.7.71 6379:主机的IP和端口号

启动哨兵

 # 没有环境变量启动方式
 cd /usr/local/redis
 ./bin/redis-sentinel ./etc/sentinel.conf
 ​
 # 有环境变量启动方式
 redis-sentinel /usr/local/redis/etc/sentinel.conf
 ​
 # 实时查看哨兵日志
 tail -f /var/log/redis/sentinel.log

从机宕机

杀死Redis-2从机进程,30秒后观察哨兵日志

注意:如果设置自启日志可能只会显示重启,解决方案在下面。

 # 查看服务进程
 ps -ef|grep redis
 ​
 # 显示服务进程
 root        5078       1  0 20:20 ?        00:00:05 /usr/local/redis/bin/redis-server 0.0.0.0:6379
 root        5521    4867  0 20:59 pts/0    00:00:00 grep --color=auto redis
 ​
 # 强制关闭服务进程
 kill -s 9 5078
 ​
 # 实时查看哨兵日志
 tail -f /var/log/redis/sentinel.log

启动Redis-2从机,观察哨兵日志(指令不成功查看是否设置环境变量)

 redis-server /usr/local/redis/etc/redis.conf

日志状态及解读

 09:30:10.071 # +sdown slave 192.168.7.72   # 1. 哨兵发现从库挂了(主观下线)
 09:31:29.078 * +reboot slave 192.168.7.72  # 2. 从库进程重新启动,哨兵检测到了
 09:31:29.121 # -sdown slave 192.168.7.72   # 3. 哨兵确认从库已恢复,解除下线标记

主机宕机

杀死Redis-1主机进程,30秒后观察哨兵日志

注意:如果设置自启日志可能只会显示重启,解决方案在下面。

 # 查看服务进程
 ps -ef|grep redis
 ​
 # 显示服务进程
 root        1109       1  0 08:20 ?        00:00:09 /usr/local/redis/bin/redis-server 0.0.0.0:6379
 root        3353    2554  0 09:02 pts/0    00:00:00 grep --color=auto redis
 ​
 # 强制关闭服务进程
 kill -s 9 1109

启动Redis-1主机,观察哨兵日志(指令不成功查看是否设置环境变量)

 redis-server /usr/local/redis/etc/redis.conf

日志状态解读

 # 关闭主库后的日志
 09:34:17.542 # +sdown master 192.168.7.71                 # 1. 哨兵发现主库挂了(主观下线)
 09:34:17.544 # +odown master 192.168.7.71                   # 2. 客观下线,触发故障转移
 09:34:17.544 # +new-epoch 4                                 # 3. 开启新纪元
 09:34:17.544 # +try-failover master 192.168.7.71            # 4. 尝试发起故障转移
 09:34:17.552 # +vote-for-leader 0318d09a...                 # 5. 投票给 Leader
 09:34:17.552 # +elected-leader master 192.168.7.71          # 6. 当选 Leader
 09:34:17.552 # +failover-state-select-slave                 # 7. 开始挑选从库
 09:34:17.615 # +selected-slave 192.168.7.73                 # 8. 选中 7.73 作为新主
 09:34:17.615 * +failover-state-send-slaveof-noone           # 9. 提升 7.73 为主库
 09:34:17.668 * +failover-state-wait-promotion               # 10. 等待提升完成
 09:34:18.582 # +promoted-slave 192.168.7.73                 # 11. 7.73 已升为主库
 09:34:18.582 # +failover-state-reconf-slaves                # 12. 重新配置其他从库
 09:34:18.629 * +slave-reconf-sent 192.168.7.72              # 13. 向 7.72 发送同步命令
 09:34:18.904 * +slave-reconf-inprog 192.168.7.72            # 14. 7.72 正在同步数据
 09:34:18.905 * +slave-reconf-done 192.168.7.72              # 15. 7.72 同步完成
 09:34:18.963 # +failover-end master 192.168.7.71            # 16. 故障转移结束
 09:34:18.963 # +switch-master 7.71→7.73                     # 17. 🎯 主库切换完成
 09:34:18.964 * +slave 192.168.7.72                          # 18. 7.72 确认为从库
 09:34:18.964 * +slave 192.168.7.71                          # 19. 原主 7.71 被加为从库
 09:34:48.968 # +sdown slave 192.168.7.71                  # 20. 原主未启动,哨兵检测为下线
 ​
 # 开启原主库后的日志
 09:43:53.989 # -sdown slave 192.168.7.71              # 1. 哨兵确认原主已启动,解除下线标记
 09:44:03.956 * +convert-to-slave slave 192.168.7.71   # 2. 原主库自动降级为从库,加入集群

日志状态说明:

 # 主服务器已被重置。
 +reset-master
 ​
 # 一个新的从服务器已经被 Sentinel 识别并关联。
 +slave
 ​
 # 从节点重启后重新加入集群(手动启动或自动恢复)。
 +reboot slave
 ​
 # 主节点重启后重新加入集群(手动启动或自动恢复)。
 +reboot master
 ​
 # 故障转移状态切换到了 reconf-slaves 状态。
 +failover-state-reconf-slaves
 ​
 # 另一个 Sentinel 开始了一次故障转移操作,或者一个从服务器转换成了主服务器。
 +failover-detected
 ​
 # 领头(leader)的 Sentinel 向实例发送了 SLAVEOF 命令,为实例设置新的主服务器。
 +slave-reconf-sent
 ​
 # 实例正在将自己设置为指定主服务器的从服务器,但相应的同步过程仍未完成。
 +slave-reconf-inprog
 ​
 # 从服务器已经成功完成对新主服务器的同步。
 +slave-reconf-done
 ​
 # 对给定主服务器进行监视的一个或多个 Sentinel 已经因为重复出现而被移除 —— 当 Sentinel 实例重启的时候,就会出现这种情况。
 -dup-sentinel
 ​
 # 一个监视给定主服务器的新 Sentinel 已经被识别并添加。
 +sentinel
 ​
 # 给定的实例现在处于主观下线状态。
 +sdown
 ​
 # 给定的实例已经不再处于主观下线状态。
 -sdown
 ​
 # 给定的实例现在处于客观下线状态。
 +odown
 ​
 # 给定的实例已经不再处于客观下线状态。
 -odown
 ​
 # 当前的纪元(epoch)已经被更新。
 +new-epoch
 ​
 # 一个新的故障迁移操作正在执行中,等待被大多数 Sentinel 选中。
 +try-failover
 ​
 # 赢得指定纪元的选举,可以进行故障迁移操作了。
 +elected-leader
 ​
 # 故障转移操作现在处于 select-slave 状态 —— Sentinel 正在寻找可以升级为主服务器的从服务器。
 +failover-state-select-slave
 ​
 # Sentinel 操作未能找到适合进行升级的从服务器。Sentinel 会在一段时间之后再次尝试寻找合适的从服务器来进行升级,又或者直接放弃执行故障转移操作。
 no-good-slave
 ​
 # Sentinel 顺利找到适合进行升级的从服务器。
 selected-slave
 ​
 # Sentinel 正在将指定的从服务器升级为主服务器,等待升级功能完成。
 failover-state-send-slaveof-noone
 ​
 # 故障转移因为超时而中止,不过最终所有从服务器都会开始复制新的主服务器。
 failover-end-for-timeout
 ​
 # 故障转移操作顺利完成。所有从服务器都开始复制新的主服务器了。
 failover-end
 ​
 # 配置变更,主服务器的 IP 和地址已经改变。这是绝大多数外部用户都关心的信息。
 +switch-master
 ​
 # 进入 tilt 模式。
 +tilt
 ​
 # 退出 tilt 模式。
 -tilt

修改配置文件(解决自动重启)

 # 编辑 systemd 服务文件:
 vim /etc/systemd/system/redis.service
 ​
 # 找到这一行:
 Restart=on-failure
 ​
 # 改为:
 Restart=no
 ​
 # 保存后重新加载 systemd:
 systemctl daemon-reload
 ​
 ​
 注:测试后可以重新添加回来并重新加载配置即可

哨兵连接查询(未测试宕机前的)

如果测试宕机新主库会发生改变

 # 您可以使用以下命令测试哨兵连接
 redis-cli -p 26379 sentinel masters
 ​
 # 该命令会返回所有主节点的信息。如果哨兵工作正常,您将看到类似以下的输出:
 1)  1) "name"
     2) "Redis1"
     3) "ip"
     4) "192.168.7.71"
     5) "port"
     6) "6379"
     7) "runid"
     8) "de55f08918972173509b577321083fd29019e9d4"
     9) "flags"
    10) "master"
    ....
    
 # 要通过哨兵获取当前的主节点地址,可以使用以下命令:
 redis-cli  -p 26379 sentinel get-master-addr-by-name Redis1
 ​
 # 显示结果
 1) "192.168.7.71"
 2) "6379"
 ​
 # 显示从库节点信息
 redis-cli -p 26379 SENTINEL slaves Redis1
 ​
 # 显示结果
 1)  1) "name"
     2) "192.168.7.72:6379"
     3) "ip"
     4) "192.168.7.72"
     5) "port"
     6) "6379"
     7) "runid"
     8) "9c7fb023b94cf13e064f9a9e94db0b287b53a09a"
     9) "flags"
    10) "slave"
    11) "link-pending-commands"
    12) "0"
    13) "link-refcount"
    14) "1"
    15) "last-ping-sent"
    16) "0"
    17) "last-ok-ping-reply"
    18) "598"
    19) "last-ping-reply"
    20) "598"
    21) "down-after-milliseconds"
    22) "30000"
    23) "info-refresh"
    24) "9343"
    25) "role-reported"
    26) "slave"
    27) "role-reported-time"
    28) "1586387"
    29) "master-link-down-time"
    30) "0"
    31) "master-link-status"
    32) "ok"
    33) "master-host"
    34) "192.168.7.71"
    35) "master-port"
    36) "6379"
    37) "slave-priority"
    38) "100"
    39) "slave-repl-offset"
    40) "36508"
    41) "replica-announced"
    42) "1"
 2)  1) "name"
     2) "192.168.7.73:6379"
     3) "ip"
     4) "192.168.7.73"
     5) "port"
     6) "6379"
     7) "runid"
     8) "3e4acf375fdba9519ed3fd7253372354cf436415"
     9) "flags"
    10) "slave"
    11) "link-pending-commands"
    12) "0"
    13) "link-refcount"
    14) "1"
    15) "last-ping-sent"
    16) "0"
    17) "last-ok-ping-reply"
    18) "598"
    19) "last-ping-reply"
    20) "598"
    21) "down-after-milliseconds"
    22) "30000"
    23) "info-refresh"
    24) "9269"
    25) "role-reported"
    26) "slave"
    27) "role-reported-time"
    28) "1586387"
    29) "master-link-down-time"
    30) "0"
    31) "master-link-status"
    32) "ok"
    33) "master-host"
    34) "192.168.7.71"
    35) "master-port"
    36) "6379"
    37) "slave-priority"
    38) "100"
    39) "slave-repl-offset"
    40) "36508"
    41) "replica-announced"
    42) "1"