目标:如何哨兵监控的架构、原理和搭建
哨兵监控架构
主从模式中,当主节点宕机之后,从节点是可以作为主节点顶上来继续提供服务,但是需要修改应用方面的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。
于是,在Redis2.8版本开始,引入了哨兵(Sentinel)这个概念,在主从复制的基础上,哨兵实现了自动化故障恢复。如上图所示,哨兵模式由两部分组成,哨兵节点和数据节点:
- 哨兵节点:哨兵节点是特殊的Redis节点,不存储数据;
- 数据节点:主节点和从节点都是数据节点。
Redis Sentinel 是分布式系统中监控Redis主从服务器,并提供服务器下线时自动故障转移功能的模式。其中三个特性为:
- 监控(Monitoring):Sentinel会不断地检查你的主服务器和从服务器是否正常运行;
- 提醒(Notification):当被监控的某个Redis服务器出现问题时,Sentinel可以通过API向管理员或者其他应用程序发送通知;
- 自动化故障迁移(Automatic failover):当一个主服务器不能正常工作时,Sentinel 会开始一次自动故障迁移操作;
- 配置提供者(Configguration provider):为客户端提供服务发现功能,客户端链接Sentinel获取当前Master节点的相关信息,当发生failover时,Sentinel将新通知客户端
Sentinel的分布式特性
Redis Sentinel 是一个分布式系统,可以在一个架构中运行多个Sentinel进程,优势如下:
- 当多个Sentinel确定Master不再可用,进行故障检测,这降低了误报的可能性
- 当在不同的服务器运行多个Sentinel进程,然后将Sentinel做集群,即使其中一个故障,也可以进行热切换,降低对客户端的影响,从而提升了系统的健壮性
- Redis客户端可连接任意Sentine来使用Redis
部署Redis Sentinel 前要了解
- Sentinel运行默认监听端口26379
- 一个健壮的部署至少需要三个Sentinel实例
- 运行Sentinel必须指定配置文件,因为系统使用此文件来保存当前状态,一遍重启Sentinel时重新加载。指定的配置文件有问题或不指定配置文件,Sentinel会拒绝启动
- 三个Sentinel实例应放在相对独立的虚拟机或者物理机中。
- 由于Redis使用的是异步复制,Sentinel + Redis 不能保证故障期间保留已确认的写入,但可以配置Sentinel允许丢失有限的写入。另外还有一些安全性比较低的部署方式
- 使用的客户端要支持Sentinel,大多数热门的都支持Sentinel,但不是全部
- 没有完全健壮的HA设置,所以要经常在测试环境中测试
- Sentinel在Docker端口影射或者网络地址转换的环境中配置要格外小心:在重新映射端口的情况下,真实端口可能与转发的端口不通,会破坏Sentinel自动发现其他Sentinel进程和master的Slave列表。
优点
- 哨兵模式是基于主从模式的,所有主从的优点哨兵都有
- 主从可以自动切换,系统更健壮,可用性更高
- Sentinel会不断检查你的主服务器和从服务器是否正常运行,当被监控的某个Redis服务器出现问题时,Sentinel可以通过API或者其他应用程序发送通知。
缺点
- 主从切换需要时间,会丢失数据
- 还是没有解决主从节点写的压力
- 主从点的写能力,存储能力收到单机限制
- 动态扩容困难复杂,对于集群,容量达到上限时在线扩容会变得很复杂
哨兵的工作原理
定时任务
Sentinel内部有三个定时任务,分别是
- 每一秒每个Sentinel对其他的Sentinel和Redis节点执行PING操作(监控),这是一个心跳检测,是失败判定的依据
- 每两秒每个Sentinel通过Master节点的channel交换信息(Publish/subscribe)
- 每十秒每个Sentinel会对Master和Slave执行INFO命令,这个任务主要达到两个目的
- 发现Slave节点
- 确认主从关系
主观下线
所谓的主观下线(Subjectively Down,简称SDOWN)指的是单个Sentinel实例对服务器做出的下线判断,即单个Sentinel认为某个服务下线(有可能是接收不到订阅,之间的网络不通等等原因)。
主管下线就是说如果服务器在给定的毫秒数之内,没有返回Sentinel发送的PING命令的回复,或者返回一个错误,那么Sentinel会将这个服务器标记为主观下线(SDOWN)。
客观下线
客观下线(Objectively Down,简称ODOWN)指的是多个Sentinel实例在对同一个服务器做出了SDOWN判断,并且通过命令互相交流之后,得出的服务器下线判断,然后开启failover。
只有足够数量的Sentinel都将一个服务器标记为主管下线之后,服务器才会被标记为客观下线(ODOWN)。只有当Master被认定为客观下线时,才会发生故障迁移。
仲裁
仲裁值得是配置文件中的quorum选项。某个Sentinel先将Master节点标记为主观下线,然后会将这个判断通过sentinel is-master-down-by-addr命令询问其他Sentinel节点是否也同样认为该addr时,该Master节点会被认为客观下线进行故障迁移。
quorum的值一般设置为Sentinel个数的二分之一加1,例如3个Sentinel就设置为2.
哨兵模式工作原理
- 每个Sentinel以每秒一次的频率向他所知的Master、Slave以及其他Sentinel节点发送一个PING命令
- 如果一个实例(Instance)距离最后一次有效回复PING命令的时间超过配置文件 own-after-milliseconds选项所指定的值,则这个实例会被Sentinel标记为主观下线。
- 如果一个Master被标记为主管下线,那么正在监控这个Master的所有Sentinel要以每秒一次的频率确认Master是否真的进入了主观下线状态
- 当有足够的Sentinel(大于等于配置文件所指定的值)在指定的时间范围内确认Master进入了主观下线状态,则Master会被标记为客观下线
- 如果Master处于ODOWN状态,则投标自动选出新的主节点。将剩余的从节点指向新的主节点继续进行数据复制;
- 在正常的情况下,每个Sentinel会以每10秒一次的频率向他已知的所有Master、Slave发送INFO命令,当Master被Sentinel标记为客观下线时,Sentinel向已下线的Master的所有Slave发送INFO命令的频率会从10秒一次改为每秒一次
- 若美欧足够数量的Sentinel同意Master已经下线,Master的客观下线状态就会被移除。若Master重新向Sentinel的PING命令返回有效回复,Master的主管下线状态就会被移除。
哨兵的搭建
编写配置文件
在3台服务器分别安装Redis,或者直接在一主二从的三台Redis服务器上配置
三个节点分别创建 sentinel.conf
并添加以下配置。
# 只有6.2以上版本的sentinel可以解析主机名 这个docker才需要开启的
sentinel resolve-hostnames yes
# 放行所有 IP 限制
bind 0.0.0.0
# 进程端口号
port 26379
# 后台启动 正常应该使用YES,Docker需要改成no
daemonize no
# 日志记录文件
logfile "/usr/local/redis/sentinel/log/sentinel.log"
# 进程编号记录文件
pidfile "/var/run/sentinel.pid"
# 指示 Sentinel 去监视一个名为 mymaster 的主服务器
sentinel monitor mymaster 172.18.0.7 6379 2
# 访问主节点的密码
# sentinel auth-pass mymaster 123456
# Sentinel 认为服务器已经断线所需的毫秒数
sentinel down-after-milliseconds mymaster 10000
# 若 Sentinel 在该配置值内未能完成 failover 操作,则认为本次 failover 失败
sentinel failover-timeout mymaster 180000
启动
先启动 3 个 Redis 服务
# 启动Redis
/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf
启动3个Sentinel服务
# 启动Sentinel
/usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel.conf
查看日志
# 查看日志
tail -f /usr/local/redis/log/sentinel.log
故障迁移的一致性
有个问题,三个Sentinel如果选不出一个领头羊,或者三个Sentinel都要去做备份迁移,那么肯定是会出错的。
解决这个方法,这里用到了分布式一致性算法Raft(共识算法),就是怎么样选举Sentinel节点为领头羊节点
- Sentinel自动故障迁移使用Raft算法来选举领头羊(Leader)Sentinel,从而确保在一个给定的周期(epoch)里,只有一个领头产生。
- 这表示在同一个周期中,不会有两个Sentinel同时被选择为领头,并且各个Sentinel在同一个节点中只会对一个领头进行投票。
- 更高的配置节点总是优于较低的节点,因此每个Sentinel都会主动使用更新的节点来代替自己的配置。
简单来说,我们可以将Sentinel配置看作是一个带版本号的状态,一个状态会以最后写入者胜出(Last-write-wins)的方式(也即是,最新的配置总是胜出的)传播至所有的其他Sentinel。
TILT模式(假如系统时间错误了)
Redis Sentinel 严重历来系统时间:为了确认实例是否可用,他会记录最后一次回复PING的时间,并和当前时间比较推断距离最后一次回复过去了多久。
然而,若系统时间发生非正常改变,或者系统非常繁忙,或进程优于谋些原因阻塞,Sentinel可能会出现一些问题。
TITL模式是一种特殊的”保护“模式,Sentinel在发生一些意料之外的问题时,会进入这个模式,降低对系统时间的依赖。
Sentinel所做的就是记录之前的中断调用时间,并和当前调用时间对比:
- 如果两次调用时间之间的差距为负值(系统时钟调整到之前的某个时间值),或者非常大(超过SENTINEL_TILT_TRIGGER时间,默认为2s),那么Sentinel进入TILT模式。
- 如果Sentinel已经进入TILT模式,那么Sentinel延迟退出TILT模式的时间。
当处于TITL模式,Sentinel或持续监控所有状态:
- 停止处理请求
- 当有实力向这个Sentinel发送SENTINEL is-master-down-by-addr 命令时,Sentinel返回负值:因为这个Sentinel所进行的下线判断已经不再准确。
如果TILT可以正常维持30秒钟(SENTINEL_TILT_PERIOD时长,默认为30s),那么Sentinel退出TILT模式,TITL模式是Sentinel的被动模式。
Comments NOTHING