首页 > 数据库 > 数据库开发技术 > 重新认识redis(五)





哨兵机制实现了主从库的自动切换,而实际生产环境中,往往是部署多个实例形成一个哨兵集群,通过多个哨兵实例共同判断,可以有效降低对主库下线的误判率。那么学习哨兵集群,需要掌握以下知识点:
1.如何配置哨兵信息?
2.哨兵集群组成?
3.哨兵集群运行机制?



部署哨兵集群时,需要了解以下配置:
sentinel monitor mymaster 主机IP 端口 quorum:设置主库的IP和端口,只有数量个数大于quorum的sentinel判断主实例失效,主实例才会下线。
sentinel down-after-milliseconds mymaster 30000:指定了sentinel认为redis实例已经失效需要的毫秒数,当实例超过该时间没有返回ping,则sentinel将该实例标记为主观下线。
sentinel can-failover mymaster yes: 是否允许sentinel修改slave->master. 如为no,则只能监控,无权修改。
sentinel parallel-syncs mymaster 值:一次性修改几个slave指向新的new master,在从redis较多的情况下,这个值越小,同步的时间越长,完成故障转移所需的时间就越长。
sentinel failover-timeout mymaster 180000:如果在该时间(ms)内未能完成failover操作,则认为该failover失败。
sentinelclient-reconfig-script mymaster /var/redis/reconfig.sh: 在重新配置new master,new slave过程,可以触发的脚本,可选。


刚开始时,哨兵实例之间彼此是不知道彼此的地址的,而是通过redis提供的pub(发布)/sub(订阅)机制。redis中提供了消息的发布和订阅功能。另外,还设置了频道来管理不同类别的消息,当消息类别相同时,则属于同一个频道,只有订阅同一个频道的应用才能进行消息沟通交换。不同哨兵就是通过订阅redis主库上的"__sentinel__:hello"频道来实现相互通信的。通过订阅该频道,哨兵获得哨兵集群中其他哨兵的ip+端口号。然后建立网络连接,从而形成哨兵集群。同时哨兵还会向主库发送INFO命令来获取从库列表,与从库建立连接,然后通过这个连接持续性地对从库进行监控。
哨兵通过与主库之间的pub/sub机制实现了集群组成,和从库连接,那么假设主从切换后了,客户端怎么知道新主库的连接信息呢?这就依赖于客户端和哨兵实例之间的pub/sub机制了。客户端通过读取哨兵的配置文件获取哨兵的地址和端口,然后和哨兵建立网络连接并执行订阅命令,以此来获取不同的事件消息。
可借助下图进行理解:



之前已经学习过,哨兵机制中,主从切换过程会进行一个下线和切换的过程,在此过程中,需要把握两个方面:
1.怎么判断下线?
2.谁来执行主从切换?
针对第一个问题,详细流程如下:当一个哨兵实例自身判断主库"主观下线后",会向其他实例发送is-master-down-by-addr命令,其他实例根据自己和主库的连接情况,回复Y(赞成票)或者N(反对票),当一个哨兵实例获取到的赞成票大于等于配置文件中设置的quorum值时,就可以标记主库为"客观下线"。
针对第二个问题,谁来执行主从切换,执行主从切换的哨兵实例称为Leader,需要经过选举投票得出,成为Leader,需要满足两个条件,其一,获得半数以上的赞成票,其二,获得的赞成票数大于等于quorum值。如果因为网络阻塞等原因导致选举失败,会等待一段时间后在此进行投票选举。一般是故障转移超时时间failover_timeout的两倍。另外,每个哨兵实例只有一次投票权。

哨兵提供端消息订阅频道很多,其中下面这几类事件较关键:
主库下线事件:主库下线事件包含以下频道:
+sdown频道:实例进入主观下线状态
-sdown频道:实例退出主观下线状态
+odown频道:实例进入客观下线状态
-odown频道:实例退出客观下线状态
从库重新配置事件:从库重新配置事件包含以下频道:
+slave-reconf-sent:哨兵发送slaveof命令重新配置从库
+slave-reconf-inprog:从库配置了新主库,但是尚未同步
+slave-reconf-done:从库配置了新主库,且和新主库完成同步。
新主库切换事件:新主库切换事件包含以下频道:
+switch-master:主库地址发生变化。
客户端通过订阅哨兵的频道,就可以获取不同的事件消息了。
redis中,主从集群一般是采用读写分离的模式,当主库发生故障后,客户端依旧可以将读请求发送给从库,对于已同步的数据,读请求可以正常响应,但是部分数据可能未来得及同步,如果这部分数据是新写数据,读请求是会失败的,如果这部分数据是更新的数据,则读请求会返回旧值。对于写请求,一般是无法响应的。
如果希望做到应用程序无感知服务中断,客户端需要能够缓存应用的写请求,然后给应用程序返回一个确认以后,然后主从切换后,新的主库负责执行缓存的写请求,另外,客户端通过订阅哨兵提供的消息频道获取新主库的信息。
使用哈希槽而不使用键值对有以下几个原因:
1.哈希槽的个数相较于键值对要少很多,当发生变化时,修改哈希槽比修改键值对少的多。
2.存储键值对与实例的关系比哈希槽与实例的关系需要的空间大得多。
3.如果记录键值对和实例的对应关系,如果使用单线程操作表,所有操作串行执行性能慢,如果是多线程操作,涉及加锁等开销,而且较于复杂。

之前学习了redis的哨兵机制,主从同步异常等知识点,本篇在之前的基础上继续了解哨兵机制的一些详细内容。

END





原文作者:DBA修行之路;如有侵权,请联系管理员删除。