1 概述
高可用(High Availability)指系统在部分节点故障时仍能持续提供服务的能力。Redis 作为核心缓存组件,主流的高可用方案有主从复制、哨兵模式、集群模式三种。本文介绍主从复制、哨兵模式两种高可用方案。
2 主从复制
通过 “一主多从” 架构实现数据同步,主节点处理写请求并异步复制数据到从节点。从节点可承担读请求,提升系统吞吐量,但主节点故障时需人工切换,存在单点风险,适用于对自动化要求不高的轻量级场景。
- 数据冗余,实现数据的热备份
- 读写分离,负载均衡。主节点负载读写,从节点负责读,提高服务器并发量
2.1 部署架构(1主多从)
2.2 复制原理
Redis 的主从复制机制均采用异步复制,我们也称为乐观复制,这种复制方式意味着不能完全保证主库和从库数据的实时一致性。Redis的主从复制机制可以根据不同的业务场景可以采用不同的应对方式。下面是一些主要场景及其对应的实现方案:
- 首次配置完成主从库之后的全量复制:在从库第一次连接到主库时,将采用psync复制方式进行全量复制。这意味着从库会从头开始复制主库中的全部数据。
- 主从正常运行期间,准实时同步:在正常运行状态下,从库通过读取主库的缓冲区来进行增量复制。这个过程涉及复制主库上发生的新的数据变更。
- 从库第二次启动(异常或主从网络断开后恢复):Append增量数据 + 准实时同步将通过读取主库的缓冲区进行部分复制。这种方式能够快速同步中断期间发生的数据变更,而不会对主库造成重大影响。
2.3 数据同步
在主从服务器建立连接确认各自身份之后,就开始数据同步,从服务器向主服务器发送PSYNC命令,执行同步操作,并把自己的数据库状态更新至主服务器的数据库状态。Redis的主从同步分为:完整重同步(full resynchronization)和部分重同步(partial resynchronization)
2.3.1 全量同步
有两种情况下是完整重同步,
- slave连接上master第一次复制的时候;
- 当主从断线,重新连接复制的时候有可能是完整重同步(详细说明见下节)
- 从服务器连接主服务器,发送SYNC命令
- 主服务器接收到SYNC命名后,开始执行bgsave命令生成RDB文件并使用缓冲区记录此后执行的所有写命令
- 主服务器basave执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令
- 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照
- 主服务器快照发送完毕后,开始向从服务器发送缓冲区中的写命令
- 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令
2.3.2 全量同步
部分重同步是用于处理断线后重复制的情况,先介绍几个用于部分重同步的部分
- runid(replication ID),主服务器运行id,Redis实例在启动时,随机生成一个长度40的唯一字符串来标识当前节点
- offset,复制偏移量。主服务器和从服务器各自维护一个复制偏移量,记录传输的字节数。当主节点向从节点发送N个字节数据时,主节点的offset增加N,从节点收到主节点传来的N个字节数据时,从节点的offset增加N
- replication backlog buffer,复制积压缓冲区。是一个固定长度的FIFO队列,大小由配置参数repl-backlog-size指定,默认大小1MB。需要注意的是该缓冲区由master维护并且有且只有一个,所有slave共享此缓冲区,其作用在于备份最近主库发送给从库的数据
当slave连接到master,会执行PSYNC 发送记录旧的master的runid(replication ID)和偏移量offset,这样master能够只发送slave所缺的增量部分。但是如果master的复制积压缓存区没有足够的命令记录,或者slave传的runid(replication ID)不对,就会进行完整重同步,即slave会获得一个完整的数据集副本。
2.4 总结
主从复制引入了数据冗余节点,提高了Redis的高可用性,同时提高了Redis服务的读负载能力。但是Master节点挂了,只能人工干预恢复环境,因此,无人值守变成刚需。
3 哨兵模式
在主从复制基础上引入独立的哨兵集群,实时监控主从节点状态。当主节点故障时,哨兵自动选举新主节点并完成拓扑重构,实现无人值守的故障转移。相比主从复制,其自动化程度更高,但仍受限于单主节点的容量上限。哨兵负责三个任务:监控,选主(选择主库)和通知。
- 监控:监控是指哨兵进程运行时,周期性(默认1秒)给所有主从节点发送 PING 命令,当主从节点收到PING 命令后,会发送一个响应命令给哨兵,这样就可以检测他们是否仍然在线运行。从库没有在规定时间内响应哨兵的PING命令,哨兵就会把它标记为"下线状态";主库没有在规定时间呢响应哨兵的PING命令,哨兵就会判定主库下线启动选主流程。
- 选主:哨兵在主库挂了以后,按照一定规则从从库中选出作为新的主库。
- 通知:哨兵将选出的新主库连接信息发给其他从库,从库和新主库建立连接,执行replicaof命令,复制数据。同时,哨兵会把新主库的连接信息通知给客户端,让它们将操作请求发送给新主库上。
3.3 部署架构
3.4 主节点下线
- SDown主观下线(Subjectively Down):单个sentinel自己主观上检测到的关于master的状态,从sentinel的角度来看,如果发送了PING心跳后,在一定时间内没有收到合法的回复,就达到了SDOWN的条件。
- ODown客观下线(Objectively Down):需要一定数量的sentinel,多个哨兵达成一致意见才能认为一个master客观上已经宕机。quorum这个参数是进行客观下线的一个依据,法定人数/法定票数 意思是至少有quorum个sentinel认为这个master有故障才会对这个master进行下线以及故障转移。因为有的时候,某个sentinel节点可能因为自身网络原因导致无法连接master,而此时master并没有出现故障,所以这就需要多个sentinel都一致认为该master有问题,才可以进行下一步操作,这就保证了公平性和高可用。
3.5 选举原理
当主节点被判断客观下线后,各个哨兵节点会进行协商,先选举出一个==领导者哨兵节点(兵王)==并由该领导者也即被选举出的兵王进行failover(故障转移)。
3.5.1 哨兵选举
监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法;Raft算法的基本思路是先到先得:即在一轮选举中,哨兵A向B发送成为领导者的申请、如果B没有同意过其他哨兵,则会同意A成为领导者。
3.5.2 主节点选择
3.6 总结
在主从复制的基础上,哨兵引入了主节点的自动故障转移,进一步提高了Redis的高可用性;但是哨兵的缺陷同样很明显:哨兵无法对从节点进行自动故障转移,在读写分离场景下,从节点故障会导致读服务不可用,这就需要对从节点做额外的监控、切换操作。 此外,哨兵仍然没有解决写操作无法负载均衡、存储能力受到单机限制的问题。