Redis开发运维实践高可用和集群架构与实践(四)

11.1.4 高可用和异常测试

11.1.4.1 测试环境介绍


sentinel的消息可以通过sentinel日志(/redis/log/sentinel.log)以及sentinel:hello订阅此频道进行查看。

11.1.4.2 手动切换测试

集群情况,2.128为主

Redis开发运维实践高可用和集群架构与实践(四)

发起主动切换:


查看sentinel日志:


在2.129上看,集群已经切换过来:

Redis开发运维实践高可用和集群架构与实践(四)


11.1.4.3 主实例宕测试

接上,此时master为2.129,找出redis实例的pid,然后kill:


此时查看sentinel日志:


从日志中可以看出已经切换到2.128,此时在2.128上看集群状态:

Redis开发运维实践高可用和集群架构与实践(四)

目前2.128为主,2.130为从,2.129上的redis宕掉。现在重启2.129上的redis实例,启动后该节点会从原先的主变为从,并对2.128进行同步,最后达到同步状态:

Redis开发运维实践高可用和集群架构与实践(四)

查看redis.conf和redis-sentinel.conf,发现都被改写。

11.1.4.4 单从实例宕测试

接上,2.129为从,此时杀掉该进程,redis.log日志记录如下:


此时集群正常提供对外服务,并不影响。

11.1.4.5 双从实例宕测试

接上,此时Master为2.128,还有一个活着的从2.130,集群状态如下:

Redis开发运维实践高可用和集群架构与实践(四)

此时,杀掉2.130的redis实例后,集群状态如下:

Redis开发运维实践高可用和集群架构与实践(四)

此时由于配置了最小slave个数为1,已经不满足,因此集群变为只读状态:

Redis开发运维实践高可用和集群架构与实践(四)

11.1.4.6 单sentinel宕测试

恢复集群状态,2.128为主,2.129、2.130为从。

Redis开发运维实践高可用和集群架构与实践(四)
此时,从2.128上看sentinel状态: Redis开发运维实践高可用和集群架构与实践(四)
由于sentinel都是对等的,在此选择对2.128上的sentinel进行进程宕测试: Redis开发运维实践高可用和集群架构与实践(四)此时,本节点sentinel日志为: Redis开发运维实践高可用和集群架构与实践(四)其他节点sentinel日志为: Redis开发运维实践高可用和集群架构与实践(四)表示2.128上的sentnel已经宕。 此时集群读写正常,在一个sentinel宕机的基础上宕master后切换正常。

11.1.4.7 双sentinel宕测试

恢复集群状态,2.128为主,2.129、2.130为从。此时,将2.128的sentinel和2.129的sentinel都宕掉。此时主从集群读写均正常。 在双方sentinel宕机时,杀掉master,主从集群切换失效,原因是因为设置sentinel 的quorum为2,最少有两个sentinel活集群才正常切换。

11.1.4.8 master所在主机整体宕测试

恢复集群状态,2.128为主,2.129、2.130为从。此时,对2.128进行宕机测试,直接关闭电源。 主从切换至2.130,从2.129指向新的主:

Redis开发运维实践高可用和集群架构与实践(四)
sentinel日志为:

Redis开发运维实践高可用和集群架构与实践(四)

11.1.4.9 slave所在主机整体宕测试

恢复集群状态,2.128为主,2.129、2.130为从。此时直接关闭2.129,这时相当于一个redis slave进程和一个sentinel进程宕。主不受影响,并且感知到一个从已经宕机。

Redis开发运维实践高可用和集群架构与实践(四)
sentinel日志记录了此事件。

Redis开发运维实践高可用和集群架构与实践(四)

11.1.4.10 脑裂测试

恢复集群状态,2.128为主,2.129、2.130为从。首先进行一个从网络分离的测试:

Redis开发运维实践高可用和集群架构与实践(四)
此时集群状态为(从master看): Redis开发运维实践高可用和集群架构与实践(四)
此时切断2.130这个链路,2.128和2.129分别为主从形成一个集群,2.130会失败,因为没有足够的sentinel进行投票完成failover。剩余集群如下: Redis开发运维实践高可用和集群架构与实践(四)
第三台机器则为slave失败状态:

Redis开发运维实践高可用和集群架构与实践(四)
此时由于没有发生切换,因此对应用没有影响。

另一种情况,如果将主机网络断开,剩余两个从成为一个新的集群,其中一个从(2.129)成为主:

Redis开发运维实践高可用和集群架构与实践(四)

原来的主机则为没有slave的主:

Redis开发运维实践高可用和集群架构与实践(四)

此时由于没有可用的slave,旧主无法写入(实际上由于网络断开也根本无法访问,因此从网络和数据库本身都不具有可写性):

Redis开发运维实践高可用和集群架构与实践(四)
新主从可以接受读写请求: Redis开发运维实践高可用和集群架构与实践(四) 此时如果旧主的网络恢复,由于它的epoch比较旧,因此会成为从,将部分同步(psync)网络宕期间产生的新数据。

从上述两种情况测试,此架构不会导致双主对外服务,也不会因为网络恢复而数据混乱。

脑裂的场景还可以进行的一个测试时多个sentinel,例如下列架构(为了便于测试在两台机器上开多端口模拟多台机器):

Redis开发运维实践高可用和集群架构与实践(四)

这个场景配置Quorum=3. 此时切断两台机器的通信网络(模拟两个机房之间通信中断),左边的机器(模拟主机房)集群不会受到影响,右边的机器(模拟灾备机房)由于不够大多数因此不会产生新的Master。

11.1.4.11 quorum测试

在一个如下的四节点环境中,

Redis开发运维实践高可用和集群架构与实践(四)

如果sentinel monitor的quorum设置为3,则宕机一台后再宕机,此时还剩余两台,存在两个sentinel,两个slave。由于quorum为3,而必须有>=max(quorum, num(sentinels)/2 +1) = max(3,2) = 3个sentinel都同意其中某一个sentinel主持failover,因此此时无sentinel可主持切换,因此测试表明,没有新的master被选出来,此时只能手动通过slaveof命令设置主从,并且手动切换(redis、sentinel和都应用不用重启):


如果sentinel monitor的quorum设置为2,则宕机一台后再宕机,此时还剩余两台,存在两个sentinel,两个slave。由于quorum为2,必须有>=max(quorum, num(sentinels)/2 +1)=max(2,2) =2个的sentinel都同意其中某一个sentinel主持failover,因此此时存在sentinel可主持切换,因此测试表明,新的master被选出来。

但是设置为2有一个危险就是如果出现如下的网络隔离状况:

Redis开发运维实践高可用和集群架构与实践(四)

集群就会脑裂,就会出现两个master。因此,生产上为了万无一失,宁可牺牲掉一定的高可用容错度也要避免脑裂。如果希望两台宕机依然可以切换,最好的方案不是降低quorum而是增多sentinel的个数,这个建议也是antirez在*中回答一个人的提问时给的建议(http://*.com/questions/27605843/redis-sentinel-last-node-doesnt-become-master#)。 如下场景测试:

Redis开发运维实践高可用和集群架构与实践(四) 此时其中两台宕机,必须有>=max(quorum, num(sentinels)/2 +1)=max(3,3) =3个的sentinel都同意其中某一个sentinel主持failover,因此此时存在sentinel可主持切换,测试结果表明此种部署方案可以正常切换。

11.1.4.12 Master hang死测试

由于我们的sentinel down-after-milliseconds为3100,即3.1s,因此在master上执行: debug sleep 3.0,系统不会切换,但是执行debug sleep 3.7或者更大的数值,系统就会判定为主sdown,进而变为odown随后发起投票切换。很难模拟取消odown的,因为时间差很短。

11.1.4.13 附:sentinel.conf被修改后的含义

port 26379 dir "/var/lib/redis/tmp" sentinel monitor mymaster 192.168.65.128 6379 2 sentinel config-epoch mymaster 18 ###确认mymater SDOWN时长 sentinel leader-epoch mymaster 18 ###同时一时间最多18个slave可同时更新配置,建议数字不要太大,以免影响正常对外提供服务 sentinel known-slave mymaster 192.168.65.129 6379 ###已知的slave sentinel known-slave mymaster 192.168.65.130 6379 ###已知的slave sentinel known-sentinel mymaster 192.168.65.130 26379 be964e6330ee1eaa9a6b5a97417e866448c0ae40 ###已知slave的唯一id sentinel known-sentinel mymaster 192.168.65.129 26379 3e468037d5dda0bbd86adc3e47b29c04f2afe9e6 ###已知slave的唯一id sentinel current-epoch 18 ####当前可同时同步的salve数最大同步阀值


本文为《Redis开发运维实践指南》内容,该书作者为黄鹏程,已授权云栖社区转载。


上一篇:C++实现RTMP协议发送H.264编码及AAC编码的音视频


下一篇:python 导入模块 import 理解