Redis Sentinel 哨兵架构


Redis Sentinel 哨兵架构

一、哨兵架构

主从架构存在以下两个问题

  • 手工故障转移
  • 写性能和存储能力受限

而 Redis Sentinel 具有以下主要功能:

  1. 监控:Sentinel 会定期监控 Redis 数据节点、以及其余 Sentinel 节点是否可达
  2. 通知:Sentinel 会将故障转移的结果通知给应用方
  3. 故障转移:当主节点故障后,从节点自动选举晋升并维护后续主从关系
  4. 配置提供:为客户端提供 Sentinel 节点集合,从中选举主节点

二、环境配置

节点环境

  • 1 Master 节点
  • 2 Slave 节点
  • 3 Sentinel 节点

目录结构

[root@bj-vmware-test1 redis]# tree .
.
├── config
│   ├── redis_server_6379.conf
│   └── sentinel_26379.conf
├── data
│   ├── 26379.log
│   ├── 6379.aof
│   ├── 6379.log
│   └── 6379.rdb
└── run
└── redis_6379.pid

master 节点配置文件

root@iZ947mgy3c5Z:/prodata/redis# cat config/redis_server_6379.conf
daemonize yes
port 6379
bind 127.0.0.1
dbfilename "6379.rdb"
appendfilename "6379.aof"
dir "/prodata/redis/data"
logfile "/prodata/redis/data/6379.log"
pidfile "/prodata/redis/run/redis_6379.pid"
appendonly yes

slave 节点配置文件

root@iZ947mgy3c5Z:/prodata/redis# cat config/redis_server_6379.conf
daemonize yes
port 6379
bind 127.0.0.1
dbfilename "6379.rdb"
appendfilename "6379.aof"
dir "/prodata/redis/data"
logfile "/prodata/redis/data/6379.log"
pidfile "/prodata/redis/run/redis_6379.pid"
appendonly yes
# 设置主节点地址端口
slaveof 192.168.2.20 6379

启动集群,主、从节点分别执行

$ redis-server config/redis_server_6379.conf

三、哨兵配置

最基础的哨兵配置

root@iZ947mgy3c5Z:/prodata/redis# cat config/sentinel_26379.conf
port 26379
daemonize yes
dir "/prodata/redis/data"
logfile "26379.log"
# 设置主节点地址端口
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

配置参数

  • sentinel monitor:配置主从复制主节点名称,以及 ip、端口,以及 quorum (法定人数),此处配置为 2,代表 >=2个 sentinel 节点认为宕机,才会触发自动 failover,否则不会进行 failover

  • sentinel down-after-milliseconds:sentinel 每秒向监控的 redis 发送 ping 命令,如果响应时间超过 30 秒,则认为 master 宕机,随后,进入法定票数判断

    首先,Sentinel 标记 master 节点为 主观下线(Subjectively Down, 简称 SDown),如果标记 master 实例的 sentinel 数超过 quorum,则将该实例标记为 客观下线(Objectively Down,简称 ODown),如果没超过 quorum 则清除该 redis 实例的主观下线标记

  • sentinel parallel-syncs:当发生 failover 后,最多允许几个 slave 同时向新选举出的 master 复制数据,默认建议设置 1,同一时间只有一台处于重新复制新主数据状态(无法提供服务),其余节点排队等待重新复制新主数据(可以提供服务)

    • 参数值过小:并发复制的实例数越少,完成整个主从架构的故障转移需要的时间越长
    • 参数值过大:大量从节点并发复制数据,导致短时间内无法提供读请求的响应
  • sentinel failover-timeout:如果整个 failover 过程超过指定毫秒,则认为本次 failover 失败

启动哨兵实例

$ redis-sentinel /prodata/redis/config/sentinel_26379.conf

四、模拟故障

通过 kill 命令结束 redis-server 进程

kill -9 redis_pid

Sentinel 节点 1 宕机日志

# 标记 master 节点为 主观下线 SDown 
2236:X 05 Jan 17:30:50.758 # +sdown master mymaster 192.168.2.50 6379
# 法定票数超过 2 票,客观下线 ODown
2236:X 05 Jan 17:30:50.825 # +odown master mymaster 192.168.2.50 6379 #quorum 2/2
# 进入新纪元
2236:X 05 Jan 17:30:50.825 # +new-epoch 4
# 开始故障转移
2236:X 05 Jan 17:30:50.825 # +try-failover master mymaster 192.168.2.50 6379
# 投票
2236:X 05 Jan 17:30:50.828 # +vote-for-leader 4aa9c09483ec5fd8ffcce32159bc76168e8e4104 4
2236:X 05 Jan 17:30:50.835 # 192.168.2.30:26379 voted for 4aa9c09483ec5fd8ffcce32159bc76168e8e4104 4
2236:X 05 Jan 17:30:50.836 # 192.168.2.50:26379 voted for 4aa9c09483ec5fd8ffcce32159bc76168e8e4104 4
2236:X 05 Jan 17:30:50.895 # +elected-leader master mymaster 192.168.2.50 6379
2236:X 05 Jan 17:30:50.895 # +failover-state-select-slave master mymaster 192.168.2.50 6379
# 从 slave 节点中选择 192.168.2.30 作为待晋升 slave 节点
2236:X 05 Jan 17:30:50.986 # +selected-slave slave 192.168.2.30:6379 192.168.2.30 6379 @ mymaster 192.168.2.50 6379
2236:X 05 Jan 17:30:50.986 * +failover-state-send-slaveof-noone slave 192.168.2.30:6379 192.168.2.30 6379 @ mymaster 192.168.2.50 6379
2236:X 05 Jan 17:30:51.039 * +failover-state-wait-promotion slave 192.168.2.30:6379 192.168.2.30 6379 @ mymaster 192.168.2.50 6379
2236:X 05 Jan 17:30:52.028 # +promoted-slave slave 192.168.2.30:6379 192.168.2.30 6379 @ mymaster 192.168.2.50 6379
2236:X 05 Jan 17:30:52.028 # +failover-state-reconf-slaves master mymaster 192.168.2.50 6379
2236:X 05 Jan 17:30:52.030 * +slave-reconf-sent slave 192.168.2.20:6379 192.168.2.20 6379 @ mymaster 192.168.2.50 6379
2236:X 05 Jan 17:30:52.977 * +slave-reconf-inprog slave 192.168.2.20:6379 192.168.2.20 6379 @ mymaster 192.168.2.50 6379
2236:X 05 Jan 17:30:52.977 * +slave-reconf-done slave 192.168.2.20:6379 192.168.2.20 6379 @ mymaster 192.168.2.50 6379
# 清除 ODown 客观下线标记
2236:X 05 Jan 17:30:53.047 # -odown master mymaster 192.168.2.50 6379
# 故障转移结束
2236:X 05 Jan 17:30:53.047 # +failover-end master mymaster 192.168.2.50 6379
# 切换新主为 192.168.2.30
2236:X 05 Jan 17:30:53.047 # +switch-master mymaster 192.168.2.50 6379 192.168.2.30 6379
# 其余两个节点作为 192.168.2.30 的从节点
2236:X 05 Jan 17:30:53.048 * +slave slave 192.168.2.20:6379 192.168.2.20 6379 @ mymaster 192.168.2.30 6379
2236:X 05 Jan 17:30:53.048 * +slave slave 192.168.2.50:6379 192.168.2.50 6379 @ mymaster 192.168.2.30 6379

Sentinel 节点 2 宕机日志

[root@Da redis]# tail -f data/26379.log
31724:X 10 Jan 10:51:38.196 # +sdown master mymaster 192.168.2.50 6379
31724:X 10 Jan 10:51:38.267 # +new-epoch 4
31724:X 10 Jan 10:51:38.269 # +vote-for-leader 4aa9c09483ec5fd8ffcce32159bc76168e8e4104 4
31724:X 10 Jan 10:51:38.280 # +odown master mymaster 192.168.2.50 6379 #quorum 3/2
31724:X 10 Jan 10:51:38.280 # Next failover delay: I will not start a failover before Wed Jan 10 10:57:39 2018
31724:X 10 Jan 10:51:39.467 # +config-update-from sentinel 192.168.2.20:26379 192.168.2.20 26379 @ mymaster 192.168.2.50 6379
31724:X 10 Jan 10:51:39.467 # +switch-master mymaster 192.168.2.50 6379 192.168.2.30 6379
31724:X 10 Jan 10:51:39.468 * +slave slave 192.168.2.20:6379 192.168.2.20 6379 @ mymaster 192.168.2.30 6379
31724:X 10 Jan 10:51:39.468 * +slave slave 192.168.2.50:6379 192.168.2.50 6379 @ mymaster 192.168.2.30 6379
31724:X 10 Jan 10:52:09.470 # +sdown slave 192.168.2.50:6379 192.168.2.50 6379 @ mymaster 192.168.2.30 6379

Sentinel 节点 3 宕机日志

5592:X 10 Jan 10:51:38.164 # +sdown master mymaster 192.168.2.50 6379
5592:X 10 Jan 10:51:38.276 # +new-epoch 4
5592:X 10 Jan 10:51:38.278 # +vote-for-leader 4aa9c09483ec5fd8ffcce32159bc76168e8e4104 4
5592:X 10 Jan 10:51:39.233 # +odown master mymaster 192.168.2.50 6379 #quorum 3/2
5592:X 10 Jan 10:51:39.234 # Next failover delay: I will not start a failover before Wed Jan 10 10:57:39 2018
5592:X 10 Jan 10:51:39.476 # +config-update-from sentinel 192.168.2.20:26379 192.168.2.20 26379 @ mymaster 192.168.2.50 6379
5592:X 10 Jan 10:51:39.478 # +switch-master mymaster 192.168.2.50 6379 192.168.2.30 6379
5592:X 10 Jan 10:51:39.479 * +slave slave 192.168.2.20:6379 192.168.2.20 6379 @ mymaster 192.168.2.30 6379
5592:X 10 Jan 10:51:39.481 * +slave slave 192.168.2.50:6379 192.168.2.50 6379 @ mymaster 192.168.2.30 6379
5592:X 10 Jan 10:52:09.518 # +sdown slave 192.168.2.50:6379 192.168.2.50 6379 @ mymaster 192.168.2.30 6379

五、实现原理

1. 三个定时任务

  1. Sentinel 定期向主、从节点发送info命令获取最新拓扑数据。
    • 简化配置
    • 动态发现从节点、更新拓扑
  2. Sentinel 定期汇报主节点以及自身情况到 __sentinel__:hello 频道,所有 sentinel 都会订阅这个频道,来了解其他 sentinel 情况以及它们对主节点的判断
    • 动态发现 sentinel 节点
    • sentinel 交换主节点情况,为后续客观下线和选举做准备。
  3. Sentinel 定期想主、从节点、以及其他Sentinel节点发送ping包,以及检测所有节点健康情况

2. 主观下线、客观下线

当第三个定期任务 ping 心跳检测失败超过 down-after-milliseconds 没有得到有效回复后,Sentinel 会对该节点做失败认定,即 主观下线 SDown,主观下线仅代表当前 sentinel 一家之言,有可能存在误判

当 Sentinel 主观下线的节点是主节点时,该 Sentinel 节点会通过sentinel is-master-down-by-addr命令向其它 sentinel 节点询问该 master 节点的状态,当其它节点赞同数超过 <quorum> 个数时,此时 sentinel 节点间会达成共识,由该 Sentinel 做 客观下线 ODown 的决定

3. 领导者选举

故障转移的工作只需要一个 Sentinel 就可以完成了,所以这里需要选举一个出来

  1. 主观下线后,执行 sentinel is-master-down-by-addr 命令时,要求自己成为领导者
  2. 收到命令的 Sentinel 节点如果没有同意过 sentinel is-master-down-by-addr,则同意该请求,否则拒绝
  3. 如果该 Sentinel 发现自己票数已经大于等于 max(quorum, num(sentinels) / 2 + 1),那么它就晋升为领导者
  4. 如果没有选举出领导者,则进入下一轮选举

4. 故障转移

领导者 Sentinel 负责故障转移

  1. 选择可用从节点
    • 过滤从节点列表中不健康的、5s内没有回复过ping的、断开超过down-after-milliseconds * 10 秒的。
    • 选择slave-priority最高的从节点列表,如果存在则返回
    • 选择复制偏移量最大的从节点(复制的最完整),如果存在则返回
    • 选择runid最小的从节点
    • 完毕
  2. 从节点升级
    • 在选择出的从节点执行slaveof no one
  3. 更新主从关系
    • 向其余从节点发送命令,让他们成为新主的从节点,复制规则和parallel-syncs有关
  4. 更新主从配置集合
    • Sentinel节点集合将原主标记为从节点,并保持关注,当其恢复时命令它复制新主数据

六、哨兵优化

误判控制

  • down-after-milliseconds: 不可达时间阈值,这会带来矛盾的问题,所以要结合网络情况来配置,不稳定的环境,频繁不稳定建议配置大一些,如果网路稳定则配置小些

  • 过大则导致发现故障和转移故障时间长

  • 从而导致应用方故障时间也拉长

##七、遗留问题

Sentinel 解决了 Master、Slave 节点的可用性问题,但是也留下的几个问题

  1. 数据存储容量无法水平扩展(Sentinel 集群添加从节点只会提升 读请求 性能)
  2. 写请求性能无法水平扩展

文章作者: Da
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Da !
  目录