上一章介绍了Redis的主从复制、读写分离,就是主机执行写命令,Slave从机能同步主机的数据,这样就是实现了主从复制,读写分离。但是万一Master主机由于某些原因挂了怎么办,这是个麻烦事情,为了解决重要问题,Redis提供了一个Sentinel机制(哨兵),以此来实现主从切换的功能,类似于zookeeper。
1、Sentinel的简介
Redis在主从复制模式中,如果出现Master主机挂掉的情况,Slave从节点并不会切换为Master主节点,那么Slave从节点会一直等待Master重新启动,这显然是不合理的,为了解决这一问题,就出现了Redis的哨兵模式(Sentinel),见名之意,哨兵巡逻监控。Sentinel主要功能:监控Redis集群中的Master主服务器时运行状态,若Master节点出现问题,能够选举出一个Slave从节点变为主节点,从而保证系统的高可用,它们通过投票的方式进行选择,但拥有50%以上投票才生效,所以至少要3个Sentinel节点,所以单个Sentinel是不可靠的。Redis哨兵模式是支持集群的,并且集群模式下的哨兵之间会自动监控。
Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。Sentinel由一个或多个Sentinel 实例 组成的Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。
例如下图所示:
在Server1 掉线后:
升级Server2 为新的主服务器:
2、Sentinel的作用
- 监控(Monitoring):哨兵(Sentinel)会不断地检查你的Master和Slave是否运作正常。
- 提醒(Notification):当被监控的某个Redis节点出现问题时,哨兵(Sentinel)可以通过API向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(Sentinel)会开始一次自动故障迁移操作。
- 它会将失效Master的其中一个Slave升级为新的Master,并让失效Master的其他Slave改为复制新的Master;
- 当客户端视图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用现在的Master替换失效的Master。
- Master和Slave服务器切换后,Master的redis.conf、Slave的redis.conf和sentinel.conf的配置文件的内容都会发生相应的改变,即Master主服务器的redis.conf配置文件中会多一行Slave的配置,sentinel.conf的监控目标会随之调换。
3、Sentinel的工作方式
- 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
- 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds (毫秒)选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。
- 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
- 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态,并且当哨兵认为主观下线的票数超过了quorum(选举)个数, 则Master会被标记为客观下线 。
- 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令 。
- 当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次 。
- 若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。
- 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。
4、Sentinel的配置(多机)
虽然哨兵模式可以切换主从节点,但是当哨兵机器挂了之后,就无法进行监控了,解决办法是哨兵也建立集群,Redis哨兵模式是支持集群的。所以配置3个哨兵和1主2从的Redis服务器来演示这个过程。
下面配置Redis的主从服务器,修改redis.conf文件如下:
(1)、配置Master节点
①、注释bind 127.0.0.1
②、禁止保护模式:protected-mode no
③、修改daemonize为yes
④、设置密码(可选,不建议设置密码,所以我就没有设置密码了):requirepass 123456
-------------------------------------------------------------
(2)配置Slave节点(在上面的基础Slave节点还需额外配置下面的信息)
①、指定主服务器。注意:只配置从服务器,主服务器不需要配置:replicaof 192.168.30.101 6379
具体可以参考上一章:Redis学习(六)----主从复制、读写分离
(3)、然后分别配置3个哨兵,每个哨兵的配置都是一样的。在Redis安装目录下有一个sentinel.conf文件,copy进行修改
①、设置哨兵后台启动
②、配置哨兵输出日志
③、设置哨兵监控的节点
(4)、开启端口:需要开启6379 和 26379 这两个端口,Linux打开端口可以参考:Linux开放指定端口(CentOS6/CentOS7)(转)
# 开启6379 firewall-cmd --zone=public --add-port=6379/tcp --permanent # 开启26379 firewall-cmd --zone=public --add-port=26379/tcp --permanent # 重启防火墙 firewall-cmd –reload # 查看端口是否开放 firewall-cmd --list-ports
(5)、当上述步骤都完成之后,我们可以进入Redis的安装目录启动Redis服务和哨兵了,通过下面的命令启动服务器和哨兵
# 进入redis安装目录bin下 cd /usr/local/redis/bin # 依次启动Redis服务器进程 ./redis-server redis.conf # 依次启动哨兵进程 ./redis-sentinel sentinel.conf # 进入redis客户端 ./redis-cli -h 192.168.30.101 -p 6379 ./redis-cli -h 192.168.30.102 -p 6379 ./redis-cli -h 192.168.30.103 -p 6379
通过 info replication 可以发现Redis主从和哨兵都启动了,并且主从关系以及建立起来了。
然后我们将Master服务关闭(即:192.168.30.101:6379),通过ShutDown命令。
这时Master主机就挂了,哨兵监控到就会马上进行投票选出一个从机作为新的Master主机,稍微等待几秒钟之后,通过查看日志可以发现,IP地址为 192.168.30.103:6379 成为了新的主机,同时,192.168.30.102:6379 和挂掉的主机成为了 192.168.30.102:6379 的从机,我们看看哨兵打印的日志:
随后如果Master主机又复活了呢?当之前挂掉的Master主机重新连接上会发生什么情况呢?我们来看一下:
可以发现原来挂掉的Master现在已经成为了192.168.30.103:6379的从节点,这样就通过Sentinel机制完成了Redis的高可用性(HA)解决方案。
自此已经完成Redis的状态:“三哨兵集群”、“一主”、“二从”的模式。
5、Sentinel的配置文件参数介绍
最后再来把哨兵机制的配置文件sentinel.conf中常用配置项说明一下:
# 打开非保护模式 protected-mode no ----------------------------------------------------- # Sentinel使用端口,默认26379 port 26379 ----------------------------------------------------- # 守护线程启动(即后台启动) daemonize yes ----------------------------------------------------- # 守护进程会使用到的一个文件 pidfile /var/run/redis-sentinel.pid ----------------------------------------------------- # 指定哨兵输出的日志文件名,默认为"",空字符串也可用于强制Sentinel登录标准输出, # 指定后我们可以通过tail -f xxx.log查看日志 logfile "/usr/local/redis/bin/sentinel.log" ----------------------------------------------------- # 哨兵sentinel的工作目录 dir "/tmp" ----------------------------------------------------- # 是否拒绝从新配置通知脚本,默认拒绝(yes). sentinel deny-scripts-reconfig yes ----------------------------------------------------- # 这个配置非常重要!!! # sentinel monitor <master-name> <ip> <redis-port> <quorum> # 告诉sentinel去监听地址为ip:port的一个master # master-name:可以自己命名的主节点名字,只能由字母A-z、数字0-9 、这三个字符".-_"组成。 # quorum:当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了 # 有多少个sentinel认为一个master失效时,master才算真正失效.需要注意的是master-ip 要写真实的ip地址而不要用回环地址(127.0.0.1)。 sentinel monitor mymaster 192.168.30.103 6379 1 ----------------------------------------------------- # 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码 # 必须为主从设置一样的验证密码,注意:这一步必须在sentinel monitor后面 # sentinel auth-pass <master-name> <password> sentinel auth-pass mymaster MySUPER--secret-0123passw0rd ----------------------------------------------------- # 故障转移的超时时间 failover-timeout 可以用在以下这些方面: # 1.同一个sentinel对同一个master两次failover之间的间隔时间。 # 2.当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同 步数据时。 # 3.当想要取消一个正在进行的failover所需要的时间。 # 4.当进行failover时,配置所有slaves指向新的master所需的大时间。 # 不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了 # 时间默认三分钟,单位为毫秒 # sentinel failover-timeout <master-name> <milliseconds> sentinel failover-timeout mymaster 180000 ----------------------------------------------------- # 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下.单位是毫秒,默认为30秒 # sentinel down-after-milliseconds <master-name> <milliseconds> sentinel down-after-milliseconds mymaster 30000 ----------------------------------------------------- # 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行同步,这个数字越小, # 完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用. # 可以通过将这个值设为1(默认就是1)来保证每次只有一个slave处于不能处理命令请求的状态 # sentinel parallel-syncs <master-name> <numslaves> sentinel parallel-syncs mymaster 1 ----------------------------------------------------- # 通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本, # 这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本 时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。 # 如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。 # 通知脚本,该配置项可选,比较常用 # sentinel notification-script <master-name> <script-path> sentinel notification-script mymaster /var/redis/notify.sh ----------------------------------------------------- # 客户端重新配置主节点参数脚本 # 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生 改变的信息。 # 以下参数将会在调用脚本时传给脚本: # <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port> # 目前<state>总是“failover”, # <role>是“leader”或者“observer”中的一个。 # 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的 # 这个脚本应该是通用的,能被多次调用,不是针对性的。 # sentinel client-reconfig-script <master-name> <script-path> sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
参考链接: