Redis Sentinel学习

定义

Redis sentinel称为哨兵模式,是Redis 高可用的实现方法,具有故障发现,故障自动转移,配置中心和客户端通知,2.8版本后sentinel生产可用。sentinel作为一个独立的进程,监控多个运行的Redis 数据库。
主要解决主从复制发生故障时,进行手动故障转移的复杂性问题,当主节点宕机后,需要手动选择一个从节点作为新的主数节点,其他作为从节点,而利用sentinel能自动完成故障转移过程。
sentinel也支持集群,因为使用单个sentinel进程了监控Redis是不可靠的,容易出现单点问题

  • 即使有一些sentinel进程宕掉了,依然可以进行Redis 集群的主从切换
  • 如果只有一个sentinel进程,如果这个进程运行出错,或者是网络堵塞,那么将无法实现Redis 集群的主从切换
  • 如果有多个sentinel,redis的客户端可以随意地连接任意一个sentinel来获得关于Redis 集群中的信息

功能和架构

  1. 功能
    • 监控Redis的运行状况
    • 当发生故障时实现主从切换。当一个master宕机之后,从它的多个slave中投票选举中一个新的master,剩余节点作为新的master的slave
  2. 架构

在这个架构中,sentinel节点会监控master和slave的相关信息,主要值得关注的是client与sentinel之间的交互:

  1. client首先需要知道sentinel节点集合和mastername信息,通过遍历它所知道的sentinel集合,获取到一个可用的sentinel节点
  2. 找到可用的sentinel节点之后,client通过 sentinel get-master-addr-by-name masterName 命令的得到master节点的地址和端口
  3. 得到master相关信息之后,会进行一次role/role replication验证,master节点会返回验证信息,至此client可以对master进行写入和读取
  4. sentine也会将redis数据节点的变化通知给客户端 - 使用发布订阅模式进行通知
  5. 上述过程不是通过代理模式实现的,即上述client和master建立关系的过程通常只需执行一次即可

故障转移过程

  1. 当一个sentinel检测master宕机并不会马上进行故障转移(主观下线),只有当后面的sentinel也都认为master不可用并达到一定数量时(客观下线),选举出一个领导者sentinel来进行故障转移操作
  2. 选出一个slave作为master,执行 slave of one 让其成为master节点
  3. 通知其余slave做为新的master的slave
  4. 等待老的master复活,若复活成功,成为新的master的slave
  5. 通知客户端发生了主从变化

实现上述故障转移依靠三个定时任务:

  1. 每10s每个sentinel对master和slave执行info操作
    • 发现slave操作
    • 确认主从关系
  2. 每2s每个sentinel通过master节点的channel交换信息
    • 发布订阅模式
    • 通过_sentinel_:hello频道交互
    • 交互对节点的"看法"和自身信息 - 可以知道其他sentinel的相关信息或投票来确定哪个sentinel来进行故障转移
  3. 每1s每个sentinel对其他sentinel和redis执行ping
    • 心跳检测,失败判定依据,比如可以作为客观下线的依据。

Sentinel配置和启动

  1. 配置文件
# sentinel运行端口
port 26379

# 守护进程启动
daemonize yes

# sentinel工作目录
dir "/usr/local/share/redis/redis-3.0.5/backs"

# sentinel 日志文件
logfile "sentinel-26379.log"

# sentinel监控的master信息 master-name ip port quorum - 当quorm个数sentinel节点认为maste
# r失联,则执行故障转移
sentinel monitor mymaster 192.168.2.23 6379 2

# 一定时间内,master没有应答哨兵sentinel, sentinel认为master主观下线 默认30秒(ping 30 次没有ping通)
sentinel down-after-milliseconds mymaster 30000

# 在进行主从切换时(故障转移),最多可以几个slave对新的master进行同步。若设置的值很小, 则同
步需要花费很长时间, 值很大,则有很多slave应为同步复制而不可用, 也会降低master节点的性能
sentinel parallel-syncs mymaster 1

# 故障转移超时时间, 应用于以下情况
# 1. 同一个sentinel对同一个master两次failover之间的间隔时间
# 2. 当一个slave从一个错误的master那里同步数据开始计算时间,直到slave被纠正为向正确的mast
# er那里同步数据时
# 3.当想要取消一个正在进行的failover所需要的时间  
# 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个时间,
# slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则进行处理
sentinel failover-timeout mymaster 180000

注:可以看到sentinel.conf配置文件主要是对master节点进行监控,通过master节点使用 info replecation 进行slave的相关信息获取,会将获取的slave信息自动添加到 sentinel.conf配置文件之中,在配置文件中的标识为:Generated by CONFIG REWRITE,需要注意的是,redis在添加slave信息的同时,也会对一些配置信息进行更改,例如sentinel down-after-milliseconds,sentinel parallel-syncs,sentinel failover-timeout会被移除,添加sentinel config-epoch,sentinel leader-epoch等配置 。

  1. 启动

redis-sentinel sentinel.conf # 启动sentinel
redis-cli -p 26379 # 连接sentinel, sentinel也当成一个普通的Redis 节点来对待

扩展

  1. 主观下线:每个sentinel节点对Redis 节点失败的"偏见",可能由于网络问题,Redis 节点不能在规定的时间内回应sentinel节点
  2. 客观下线:所有sentin节点对Redis 节点失败达成"共识",即sentinel节点中认为Redis 节点可以进行客观下线的个数超过quorum的个数,此时可以真正进行故障转移操作。其中达成共识通过sentinel is-master-down-by-addr命令询问其他sentinel节点的"意见"来完成的
  3. 领导者选举
    • 原因:只需要一个sentinel节点来进行故障转移
    • 如何:1. 每个做主观下线的sentinel节点通过sentinel is-master-down-by-addr 来询问其他sentinel节点的"意见"是否要对master节点进行客观下线的时候,通过也会要求将其设置为领导者;2. 收到命令的sentinel节点如果没有同意其他sentinel节点成为领导者的请求,那就同意,否则拒绝;3. 如果该sentinel节点发现自己的票数超过了sentinel集合半数且超过了quorum,那么它将成为领导者来进行故障处理;4. 如果有多个sentin节点成为领导者,则过一段时间再进行选举
  4. 如何选择合适的slave让其成为master
    • 选择 slave-priority优先级最高的slave节点
    • 若全部优先级相同,则选择复制偏移量最大(与以前的master节点数据最接近)的slave节点
    • 若上述都不成立,则选择runId最小的节点,即启动最早的slave

运维问题

  1. 主节点手动下线,进行故障转移
    sentinel failover masterName
  2. 高可用的读写分离
    sentinel只会对master节点进行故障转移,对于slave节点只有进行主观下线,所以要实现高可用的读写分离,客户端要关注slave节点的变化,例如关注以下三个消息: +switch-master: 从节点晋升为主节点,+conver-to-slave: 原主节点降为从节点,+sdown: 主观下线

参考资料

[1] https://segmentfault.com/a/1190000002680804
[2] https://coding.imooc.com/class/151.html

Author: HB
Link: http://www.huangbin.fun/Redis-Sentinel学习.html
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.