总结了Redis的几种高可用方式,对于做后端模块的同学来说,可以根据/或是借鉴其思路做自己的模块可用性部署。
主从热备,是高可用性中最基础的解决方案,主要作用于主机异常宕机后,可以由备机来接管主机业务。并且此时备机的数据和宕机前的主机是一致的。而主从热备的核心就在于主从复制。
主从复制
主从复制可以分为两步:
数据同步之部分重同步
从服务器对主服务器的同步可以分为两种情况:
对于第二种情况,如果每次断线后都进行全量的数据复制可能会造成效率非常底效(如果断线的时间很短,断线期间执行的写命令很少,这种情况下重新执行复制是非常低效的)。
2. 命令传播
心跳检测
心跳检测也是主备中必不可缺少的一环,其主要的作用有:
Sentinel(哨兵)也是高可用性解决方案,由一个或者多个Sentinel实例组成的Sentinel系统,可以监视任意多个主从服务器,并在被监视的主服务器宕机后,自动将宕机主服务器的从服务器升级为新的主服务器。相比热备模式,可用性更高,功能更加完善,解决了热备中可能存在的一些问题,例如双活。
Sentinel系统处理主机异常的流程
Sentinel实例结构
哨兵的实例使用sentinelState结构表示,记录了哨兵的运行时状态和一些初始化的数据。其中最重要的一个字段为被哨兵监视的主服务器实例集合,采用字典的结构来存放,键为主服务器的名称,值为主服务器对应的实例结构sentinelRedisInstance。
sentinelRedisInstance中包含的属性非常多,其中比较核心的有主服务器的从服务器实例集合、监视主服务器的其他哨兵实例集合、用于检测故障时的一些阙值等。主服务器实例通过配置文件来初始化,主服务器中的从服务器实例集合以及哨兵实例集合则在各模块交流中自动生成。
初始化哨兵实例的最后一步就是建立哨兵和主服务器之间的网络连接。哨兵实例会建立两个连向主服务器的网络连接:命令连接和订阅连接。
哨兵系统中各模块交流过程
频率为10s一次的INFO命令,发送端为Sentinel,接收端为主服务器。主服务器会回复自身的信息以及自身从服务器的信息,Sentinel通过主服务器的回复信息来更新主服务器的实例。如果从服务器的信息不存在主服务器的实例中,则初始化主服务器的从服务器信息实例信息,并建立Sentinel到从服务器的连接(同主服务器一样使用两条网络连接,并且使用INFO命令来获取)。若存在则更新从服务器实例信息。
频率为2s一次发送命令到hello频道,发送端为Sentinel,接收端为订阅了hello频道的其他服务器。Sentinel会将自己的信息和自己监听的服务器信息发送到hello频道中,其他Sentinel在接收到该条信息后,如果和发送端Sentinel监听是同一个服务器,则会更新相应服务器实例信息以及服务器实例包含的Sentinel实例信息(如上哨兵A、哨兵B例子)。并且监听同一个服务器的Sentinel间会相互连接。
频率为1s一次的PING命令,相当于心跳检测,用于判断服务器是否下线。
选举领头的Sentinel来做故障转移
Sentinel系统选举领头Sentinel采用的方法是Raft算法
。其大致的原理是:
新主服务器的挑选
集群是一种分布式高可用性部署方案。集群通过分片来进行数据共享,并提供复制和故障转移功能。
集群由节点组成
节点使用clusterNode数据结构表示,每个节点会使用clusterNode记录自己的当前状态,并为集群中其他节点都创建相应的clusterNode结构(记录在clusterState结构中)。
每个节点都保存着一个clusterState的结构,该结构记录了节点所处集群的状态信息。并且其中使用字典结构保存了集群中其他节点的信息,key为其他节点的名称,值为其他节点状态clusterNode。
各个独立的节点通过握手的方式连接起来,构成一个包含多个节点的集群。
集群槽管理
Redis集群通过分片的方式来保存数据库中的键值对:整个集群被分为16384个槽,集群中每个节点可以处理0个或最多16384个槽,redis客户端保存的每个键值对都属于这16384个槽其中的一个。只有当所有槽都有节点在处理时,集群才处于上线状态。
注:一些分布式部署中使用哈希环
来做分片管理,redis使用槽来做,目的都是减少局部变更对整体造成的影响。
节点复制和故障转移
Redis集群中的节点分为主节点和从节点,主节点负责处理槽,从节点则用于复制主节点(复制的方式和热备中复制的方式一致),并在主节点下线后代替下线主节点继续处理命令请求。
一个节点成为某个主节点的从节点,会通过消息发给集群中其他节点,最终集群中所有的节点都会知道,并且他们会更新clusterState结构中保存了该主节点的信息(更新主节点结构中的从节点名单)。
节点故障检测:集群中的每个节点会定期地向集群中其他节点发送PING消息,以此来检测对上是否在线。
集群从多个从节点中选择新的主节点方法(raft算法,类似领头Sentinel选举):
消息
集群中通过各个节点通过发送和接受消息来进行通信。节点发送的消息主要有以下五种:
注:Redis集群中各个节点通过Gossip协议
来交换各种关于不同节点的状态信息。
将自己的模块配置成高可用思路总结:将可用性部署做成独立的模块组合到自己的模块中去。依具体的业务而定,不同的模式下业务的执行过程可能不同,但是其核心业务还是一致的,可以剥离出来。尽量做到业务和部署分离。