Redis高可用(2.1):故障转移(哨兵)

哨兵(Sentinel)介绍

Redis-Sentinel是官方推荐的高可用解决方案,当redis在做master-slave的高可用方案时,假如master宕机了,redis本身(以及其很多客户端)都没有实现自动进行主备切换,而redis-sentinel本身也是独立运行的进程,可以部署在其他与redis集群可通讯的机器中监控redis集群。

Sentinel(哨兵)是用于监控redis集群中Master状态的工具,支持以集群的方式部署,生产环境建议至少部署3个节点的哨兵。

 

作用

1、集群监控,负责监控redis master和slave进程是否正常工作

2、故障转移,如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Master作为Slave 

3、配置中心,Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,slave_redis.conf中原slaveof配置会被移除,sentinel.conf的监控目标会随之调换。哨兵为客户端提供服务发现,客户端链接哨兵,哨兵提供当前最新可用的master的地址,如果出现切换,也就是master挂了,哨兵会提供客户端一个新地址。

4、消息通知,如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员

 

 Sentinel工作方式

1、每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他Sentinel实例发送一个PING命令

2、如果一个实例(instance)距离最后一次有效回复PING命令的时间超过down-after-milliseconds选项所指定的值,则这个实例会被Sentinel标记为主观下线。

3、如果一个Master被标记为主观下线,则正在监视这个Master的所有Sentinel要以每秒一次的频率确认Master的确进入了主观下线状态。

4、当有足够数量的Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态,则Master会被标记为客观下线

5、在一般情况下,每个Sentinel会以每10秒一次的频率向它已知的所有Master,Slave发送INFO命令

6、当Master被Sentinel标记为客观下线时,Sentinel向下线的Master的所有Slave发送INFO命令的频率会从10秒一次改为每秒一次

7、若没有足够数量的Sentinel同意Master已经下线,Master的客观下线状态就会被移除。若Master重新向Sentinel的PING命令返回有效回复,Master的主观下线状态就会被移除。

 

主观下线和客观下线

主观下线:SubjectivelyDown,简称SDOWN,指的是当前Sentinel实例对某个redis服务器做出的下线判断。

客观下线:ObjectivelyDown,简称ODOWN,指的是多个Sentinel实例在对MasterServer做出SDOWN判断,并且通过SENTINEL is-master-down-by-addr命令互相交流之后,得出的MasterServer下线判断,然后开启failover.

 

redis的sentinel系统用来管理多个redis服务器,可以确保在一个master节点上实现HA的集群。该系统主要执行三个任务:

a、监控(Monitoring):RedisSentinel实时监控主服务器和从服务器运行状态。

b、提醒(notification):当被监控的某个Redis服务器出现问题时,RedisSentinel可以向系统管理员发送通知,也可以通过API向其他程序发送通知

一个简单的主从结构加sentinel集群的架构图如下:


 上图是一主一从节点,加上两个部署了sentinel的集群,sentinel集群之间会互相通信,沟通交流redis节点的状态,做出相应的判断并进行处理,这里的主观下线状态和客观下线状态是比较重要的状态,它们决定了是否进行故障转移可以通过订阅指定的频道信息,当服务器出现故障得时候通知管理员

c、故障转移(failover)

 

配置文件配置可参考sentinel.conf。

增加如下配置:

#后台运行
daemonize yes
日志文件
logfile /usr/local/redis/logs/sentinel.log

 修改如下配置:

#运行端口号(确保防火墙中增加该号码的过滤)
port 26379
#绑定本机ip(sentinel集群中每个实例的配置除了此项不同,其他均可保持一致)
bind 192.168.0.100
####下面的配置可以配置多组,用于对不同的master进行监控####
#配置监控的master节点(mymaster为sentinel集群中对一组redis实例监控的代号,可自定义名称,保证sentinel集群中的名称一致即可)
--mymaster:自定义名称,后续其他配置项均基于此配置,表示配置项仅对当前master生效
--192.168.0.200:master节点ip
--6379:master节点端口号
--2:票数,<=count(sentinel),当master被标记为主观下线后,集群中其他sentinel对master进行是否下线的侦测从而汇总出一个票数,如果票数大于等于配置的值(此处为2),则master节点被标记为客观下线,随后进行故障转移
sentinel monitor mymaster 192.168.0.200 6379 2
#sentinel对master进行ping,如果配置时间(30s)没有得到回复,则master被标记为主观下线
sentinel down-after-milliseconds mymaster 30000
#故障转移,如果在该时间(ms)内未能完成failover操作,则认为该failover失败
sentinel failover-timeout mymaster 180000
#配置在进行故障转移时,运行多少个slave进行数据备份同步(越少速度越快),即有1个slave此时不能对外提供服务
sentinel parallel-syncs mymaster 1 
#设置master和slave节点密码,如果有,必须一样
sentinel auth-pass mymaster 123456
#针对节点为master时有效,要求至少有1个slave,数据复制和同步的延迟不能超过10秒。否则,master将拒绝写数据。可用于降低异步复制和脑裂导致的数据丢失。
min-slaves-to-write 1
min-slaves-max-lag 10

 

常用命令:

#连接当前sentinel(同连接redis类似)

redis-cli -h 127.0.0.1 -p 26379

#sentinel的基本状态信息 

info

#显示被监控的所有master以及它们的状态

sentinel masters

#显示指定master的信息和状态

sentinel master [sentinel中自定义的master名]

#显示指定master的所有slave以及它们的状态

sentinel slaves [sentinel中自定义的master名]

#返回指定master的ip和端口,如果正在进行failover或者failover已经完成,将会显示被提升为master的slave的ip和端口

sentinel get-master-addr-by-name [sentinel中自定义的master名]

#重置名字匹配该正则表达式的所有的master的状态信息,清楚其之前的状态信息,以及slaves信息

sentinel reset [sentinel中自定义的master名]

#列出指定名称下其他sentinel信息

sentinel sentinels [sentinel中自定义的master名]

#当主服务器失效时,在不询问其他Sentinel意见的情况下,强制开始一次自动故障迁移,但是它会给其他sentinel发送一个最新的配置,其他sentinel会根据这个配置进行更新

sentinel failover [sentinel中自定义的master名]

 

哨兵节点的增加和删除

增加sentinal,会自动发现。删除sentinal的步骤:

(1)停止sentinal进程

(2)SENTINEL RESET *,在所有sentinal上执行,清理所有的master状态

(3)SENTINEL MASTER mastername,在所有sentinal上执行,查看所有sentinal对数量是否达成了一致

 

故障转移流程

1、由sentinel主动发起failover或者发现主服务器已经进入客观下线状态。

2、sentinel对我们的当前纪元(epoch)进行自增,并尝试在这个纪元中当选为此次failover的总指挥。

3、如果当选失败,那么在设定的故障迁移超时时间的两倍之后,重新尝试当选。如果当选成功,那么执行以下步骤。

4、选出一个从redis实例,并将它升级为主redis实例。

5、向被选中的从redis实例发送SLAVEOF NO ONE 命令,让它转变为主redis实例。

6、通过发布与订阅功能, 将更新后的配置传播给所有其他Sentinel,其他 Sentinel对它们自己的配置进行更新。

7、向已下线主服务器的从服务器发送SLAVEOF命令,让它们去复制新的主服务器。

8、当所有从redis实例都已经开始复制新的主redis实例时, 领头Sentinel 终止这次故障迁移操作。

 

日志说明

+reset-master <instance details> :主服务器已被重置。

+slave <instance details> :一个新的从服务器已经被 Sentinel 识别并关联。

+failover-state-reconf-slaves <instancedetails> :故障转移状态切换到了reconf-slaves 状态。

+failover-detected <instance details>:另一个 Sentinel 开始了一次故障转移操作,或者一个从服务器转换成了主服务器。

+slave-reconf-sent <instance details>:领头(leader)的 Sentinel 向实例发送了 SLAVEOF 命令,为实例设置新的主服务器。

+slave-reconf-inprog <instancedetails> :实例正在将自己设置为指定主服务器的从服务器,但相应的同步过程仍未完成。

+slave-reconf-done <instance details>:从服务器已经成功完成对新主服务器的同步。

-dup-sentinel <instance details> :对给定主服务器进行监视的一个或多个 Sentinel 已经因为重复出现而被移除 —— 当 Sentinel 实例重启的时候,就会出现这种情况。

+sentinel <instance details> :一个监视给定主服务器的新 Sentinel 已经被识别并添加。

+sdown <instance details> :给定的实例现在处于主观下线状态。

-sdown <instance details> :给定的实例已经不再处于主观下线状态。

+odown <instance details> :给定的实例现在处于客观下线状态。

-odown <instance details> :给定的实例已经不再处于客观下线状态。

+new-epoch <instance details> :当前的纪元(epoch)已经被更新。

+try-failover <instance details> :一个新的故障迁移操作正在执行中,等待被大多数 Sentinel 选中(waiting to be elected by themajority)。

+elected-leader <instance details> :赢得指定纪元的选举,可以进行故障迁移操作了。

+failover-state-select-slave <instancedetails> :故障转移操作现在处于select-slave 状态 —— Sentinel 正在寻找可以升级为主服务器的从服务器。

no-good-slave <instance details> :Sentinel 操作未能找到适合进行升级的从服务器。Sentinel 会在一段时间之后再次尝试寻找合适的从服务器来进行升级,又或者直接放弃执行故障转移操作。

selected-slave <instance details> :Sentinel 顺利找到适合进行升级的从服务器。

failover-state-send-slaveof-noone<instance details> :Sentinel 正在将指定的从服务器升级为主服务器,等待升级功能完成。

failover-end-for-timeout <instancedetails> :故障转移因为超时而中止,不过最终所有从服务器都会开始复制新的主服务器(slaves will eventually be configured to replicate with the newmaster anyway)。

failover-end <instance details> :故障转移操作顺利完成。所有从服务器都开始复制新的主服务器了。

+switch-master <master name><oldip> <oldport> <newip> <newport> :配置变更,主服务器的 IP 和地址已经改变。 这是绝大多数外部用户都关心的信息。

+tilt :进入 tilt 模式。

-tilt :退出 tilt 模式

 

注意事项:

1、由于redis服务端和jedis客户端对读写分离支持的并不友好,所以基于当前结构,要实现真正意义上的读写分离,还需要修改jedis源码或进行二次封装,成本较高。实际上,在后期缓存数据较多时或读压力较大时,redis官方更推荐以集群(cluster)的方式存储数据(slot),多个slot将热点数据分散,主从+故障转移保证redis的高可用。

2、本文所讲的高可用基于实现(单)master节点的高可用(后期实现master cluster,集群中每个master的高可用与本文一致,即主从+故障转移(master cluster下的故障转移不是基于哨兵机制))

3、一主多从也属于redis集群的一种

猜你喜欢

转载自hengdu.iteye.com/blog/2403668