在前面讲的 master/slave 模式,在一个典型的一主多从的系统中,slave 在整个体系中起到了数据冗余备份和读写分离的作用。当 master 遇到异常终端后,开发者可以通过手动方式选择一个 slave 数据库来升级到 master,使得系统能够继续提供服务。然后这个过程需要人工干预,比较麻烦; redis 并没有提供自动 master 选举功能,而是需要借助一个哨兵来进行监控。
顾名思义,哨兵的作用就是监控 Redis 系统的运行状况,它的功能包括两个
哨兵是一个独立的进程,使用哨兵后的架构如下图所示,同时为了保证哨兵的高可用,我们会对 Sentinel 做集群部署,因此 Sentinel 不仅仅监控 Redis 所有的主从节点,Sentinel 也会实现相互监控。
在前面主从复制的基础上,增加三个 sentinel 节点,来实现对 redis 中 master 选举的功能。
sentinel 哨兵的配置方式如下:
cp sentinel.conf /usr/local/redis/bin/sentinel.conf
# 其中name表示要监控的master的名字,这个名字是自己定义,ip和port表示master的ip和端口号,最后一个2表示最低通过票数,也就是说至少需要几个哨兵节点认为master下线才算是真的下线 sentinel monitor mymaster 192.168.183.130 6379 2 sentinel down-after-milliseconds mymaster 5000 # 表示如果5s内mymaster没响应,就认为SDOWN sentinel failover-timeout mymaster 15000 # 表示如果15秒后,mysater仍没活过来,则启动failover,从剩下的slave中选一个升级为master logfile "/usr/local/redis/logs/sentinels.log" # 需要提前创建好文件
./redis-sentinel sentinel.conf
127461:X 27 Nov 2021 19:30:51.035 # +sdown sentinel f40bd964ad08ae0665f9644e4f372082726a8bf0 192.168.183.131 26379 @ mymaster 192.168.183.130 6379 34322:X 27 Nov 2021 19:31:02.189 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 34322:X 27 Nov 2021 19:31:02.189 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=34322, just started 34322:X 27 Nov 2021 19:31:02.189 # Configuration loaded 34323:X 27 Nov 2021 19:31:02.205 * Running mode=sentinel, port=26379. 34323:X 27 Nov 2021 19:31:02.205 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 34323:X 27 Nov 2021 19:31:02.205 # Sentinel ID is 978f5f62b49eed8795e05f8ea8cb8472a922c473 34323:X 27 Nov 2021 19:31:02.205 # +monitor master mymaster 192.168.183.130 6379 quorum 2
其他两个节点的配置和上面完全相同,都去监视 master 节点即可,主要,sentinel.conf 文件中 master 节点的 ip 一定不能输 127.0.0.1,否则其他 sentinel 节点无法和它通信
当其他 sentinel 哨兵节点启动后,第一台启动的 sentinel 节点还会输出如下日志,表示有其他 sentinel 节点加入进来。
34323:X 27 Nov 2021 19:31:32.246 # +sdown sentinel e027f28d80277b6d626ea6251a3f6a263dc96f11 192.168.183.132 26379 @ mymaster 192.168.183.130 6379 34323:X 27 Nov 2021 19:31:32.247 # +sdown sentinel f40bd964ad08ae0665f9644e4f372082726a8bf0 192.168.183.131 26379 @ mymaster 192.168.183.130 6379
相关问题:
- 可能会遇到允许链接数不足的情况,通过以下方法解决;
#查看系统限制 [root@centos224]# ulimit -a #设置“open files”数量 [root@centos224]# ulimit -n 10032
- 设置日志路径的时候需要提前将路径创建好,否则会启动失败。
我们直接把 redis 主从复制集群的 master 节点,通过./redis-cli shutdown
命令停止,于是我们观察三个 sentinel 哨兵的日志,先来看第一台启动的 sentinel 日志,得到如下内容。
34323:X 27 Nov 2021 19:34:53.843 # +new-epoch 1 34323:X 27 Nov 2021 19:34:53.845 # +vote-for-leader f40bd964ad08ae0665f9644e4f372082726a8bf0 1 34323:X 27 Nov 2021 19:34:53.861 # +odown master mymaster 192.168.183.130 6379 #quorum 3/2 34323:X 27 Nov 2021 19:34:53.862 # Next failover delay: I will not start a failover before Sat Nov 27 19:40:54 2021 34323:X 27 Nov 2021 19:34:54.106 # +config-update-from sentinel f40bd964ad08ae0665f9644e4f372082726a8bf0 192.168.183.131 26379 @ mymaster 192.168.183.130 6379 34323:X 27 Nov 2021 19:34:54.107 # +switch-master mymaster 192.168.183.130 6379 192.168.183.132 6379 34323:X 27 Nov 2021 19:34:54.107 * +slave slave 192.168.183.131:6379 192.168.183.131 6379 @ mymaster 192.168.183.132 6379 34323:X 27 Nov 2021 19:34:54.107 * +slave slave 192.168.183.130:6379 192.168.183.130 6379 @ mymaster 192.168.183.132 6379 34323:X 27 Nov 2021 19:35:24.138 # +sdown slave 192.168.183.130:6379 192.168.183.130 6379 @ mymaster 192.168.183.132 6379
+sdown 表示哨兵主观认为 master 已经停止服务了。
+odown 表示哨兵客观认为 master 停止服务了。
接着哨兵开始进行故障恢复,挑选一个 slave 升级为 master,其他哨兵节点的日志。
21754:X 27 Nov 2021 19:34:53.731 # +sdown master mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:53.833 # +odown master mymaster 192.168.183.130 6379 #quorum 2/2 21754:X 27 Nov 2021 19:34:53.833 # +new-epoch 1 21754:X 27 Nov 2021 19:34:53.833 # +try-failover master mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:53.836 # +vote-for-leader f40bd964ad08ae0665f9644e4f372082726a8bf0 1 21754:X 27 Nov 2021 19:34:53.843 # beb6d7194480914f61d81d7624b07c1484697f66 voted for f40bd964ad08ae0665f9644e4f372082726a8bf0 1 21754:X 27 Nov 2021 19:34:53.843 # 978f5f62b49eed8795e05f8ea8cb8472a922c473 voted for f40bd964ad08ae0665f9644e4f372082726a8bf0 1 21754:X 27 Nov 2021 19:34:53.891 # +elected-leader master mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:53.892 # +failover-state-select-slave master mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:53.963 # +selected-slave slave 192.168.183.132:6379 192.168.183.132 6379 @ mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:53.963 * +failover-state-send-slaveof-noone slave 192.168.183.132:6379 192.168.183.132 6379 @ mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:54.041 * +failover-state-wait-promotion slave 192.168.183.132:6379 192.168.183.132 6379 @ mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:54.052 # +promoted-slave slave 192.168.183.132:6379 192.168.183.132 6379 @ mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:54.052 # +failover-state-reconf-slaves master mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:54.101 * +slave-reconf-sent slave 192.168.183.131:6379 192.168.183.131 6379 @ mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:54.953 # -odown master mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:55.105 * +slave-reconf-inprog slave 192.168.183.131:6379 192.168.183.131 6379 @ mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:55.105 * +slave-reconf-done slave 192.168.183.131:6379 192.168.183.131 6379 @ mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:55.163 # +failover-end master mymaster 192.168.183.130 6379 21754:X 27 Nov 2021 19:34:55.163 # +switch-master mymaster 192.168.183.130 6379 192.168.183.132 6379 21754:X 27 Nov 2021 19:34:55.163 * +slave slave 192.168.183.131:6379 192.168.183.131 6379 @ mymaster 192.168.183.132 6379 21754:X 27 Nov 2021 19:34:55.163 * +slave slave 192.168.183.130:6379 192.168.183.130 6379 @ mymaster 192.168.183.132 6379
+try-failover 表示哨兵开始进行故障恢复
+failover-end 表示哨兵完成故障恢复
+slave 表示列出新的 master 和 slave 服务器,我们仍然可以看到已经停掉的 master,哨兵并没有清除已停止的服务的实例,这是因为已经停止的服务器有可能会在某个时间进行恢复,恢复以后会以 slave 角色加入到整个集群中。
1):每个 Sentinel 以每秒钟一次的频率向它所知的 Master/Slave 以及其他 Sentinel 实例发送一个 PING 命令
2):如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。
3):如果一个 Master 被标记为主观下线,则正在监视这个 Master 的所有 Sentinel 要以每秒一次的频率确认 Master 的确进入了主观下线状态。
4):当有足够数量的 Sentinel(大于等于配置文件指定的值:quorum)在指定的时间范围内确认 Master 的确进入了主观下线状态, 则 Master 会被标记为客观下线 。
5):在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有 Master,Slave 发送 INFO 命令
6):当 Master 被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次 ,若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。
8):若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。
**主观下线:**Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个 redis 服务器做出的下线判断。
**客观下线:**Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对 Master Server 做出 SDOWN 判断,并且通过 SENTINEL 之间交流后得出 Master 下线的判断。然后开启 failover故障恢复。
当 redis 中的 master 节点被判定为客观下线之后,需要重新从 slave 节点选择一个作为新的 master 节点,那现在有三个 sentinel 节点,应该由谁来完成这个故障转移过程呢?所以这三个 sentinel 节点必须要通过某种机制达成一致,在 Redis 中采用了 Raft 算法来实现这个功能。
每次 master 出现故障时,都会触发 raft 算法来选择一个 leader 完成 redis 主从集群中的 master 选举功能。
了解 raft 算法之前,我们来了解一个拜占庭将军问题。
拜占庭将军问题(Byzantine failures),是由莱斯利・兰伯特提出的点对点通信中的基本问题。具体含义是在存在消息丢失的不可靠信道上试图通过消息传递的方式达到一致性是不可能的。
拜占庭位于如今的土耳其的伊斯坦布尔,是东罗马帝国的首都。由于当时拜占庭罗马帝国国土辽阔,为了达到防御目的,每个军队都分隔很远,将军与将军之间只能靠信差传消息。在战争的时候,拜占庭军队内所有将军和副官必须达成一致的共识,决定是否有赢的机会才去攻打敌人的阵营。但是,在军队内有可能存有叛徒和敌军的间谍,左右将军们的决定又扰乱整体军队的秩序。在进行共识时,结果并不代表大多数人的意见。这时候,在已知有成员谋反的情况下,其余忠诚的将军在不受叛徒的影响下如何达成一致的协议,这就是是著名的拜占庭问题。
拜占庭将军问题本质上所描述的是计算机领域中的一个协议问题,拜占庭帝国军队的将军们必须全体一致的决定是否攻击某一支敌军。问题是这些将军在地理上是分隔开来的,并且将军中存在叛徒。叛徒可以任意行动以达到以下目标:
如果叛徒达到了这些目的之一,则任何攻击行动的结果都是注定要失败的,只有完全达成一致的努力才能获得胜利 。
拜占庭假设是对现实世界的模型化,由于硬件错误、网络拥塞或断开以及遭到恶意攻击,计算机和网络可能出现不可预料的行为,所以如何在这样的环境下达成一致,这就是所谓的数据一致性问题。
回到 Sentinel 中,这三个 Sentinel 节点,需要选择一个节点来负责针对 redis 集群进行故障恢复,那这三个节点中谁能做这个事情?因此同样需要基于某个机制来达成共识。
在很多中间件中都需要用到数据一致性算法,最直观的是像 zookeeper 这样一个组件,他的高可用设计是由 leader 和 follow 组成,当 leader 节点因为异常宕机了, 需要从生下的 follow 节点选举出一个新的 leader 节点,那么这个选举过程需要集群中所有节点达成一致,也就是只有所有节点都赞同某个 follow 节点成为 leader,它才能成为 leader 节点。而这个共识达成的前提是所有节点需要对某个投票结果达成一致,否则就无法选举出新的 leader,因此这里必然需要用到共识算法。
Raft 算法动画演示地址: http://thesecretlivesofdata.com/raft/
Raft 算法的核心思想:先到先得,少数服从多数。
怎么让一个原来的 slave 节点成为主节点?
如何选择合适的 slave 节点成为 master 呢?有四个因素影响。
监控:Sentinel 会不断检查主服务器和从服务器是否正常运行。
通知:如果某一个被监控的实例出现问题,Sentinel 可以通过 API 发出通知。
自动故障转移(failover):如果主服务器发生故障,Sentinel 可以启动故障转移过程。把某台服务器升级为主服务器,并发出通知。
配置管理:客户端连接到 Sentinel,获取当前的 Redis 主服务器的地址。