Redis是应用广泛的基础软件之一。对于架构师和运维人员来说,了解Redis的高可用解决方案及其背后的原理是必备的基础知识。本文作者对Redis高可用的各个方面进行了深入剖析,并做了有效的总结,相信能对读者起到很好的引领作用。Redis为了实现高可用,采用了以下两种方式:主从复制数据。哨兵用于监视数据节点的运行。一旦主节点出现问题,从节点将继续服务。主从复制在Redis中,主从节点复制数据可以分为全量复制和部分复制。旧版本全量拷贝功能的实现全量拷贝是使用Snyc命令实现的,过程如下:从服务器向主服务器发送Sync命令。主服务器收到Sync命令后,调用Bgsave命令生成最新的RDB文件,并将该文件同步到从服务器,这样从服务器加载RDB文件后,状态会和从服务器保持一致主服务器在执行Bgsave命令时。主服务器将命令缓冲区中存储的写命令同步给从服务器,从服务器执行这些命令,使从服务器的状态与主服务器的当前状态一致。旧版本的全量复制功能最大的问题是,当从服务器断开重连时,即使从服务器上已经有部分数据,也需要全量复制,效率很低,所以新版Redis在这部分做了改进。新版本全量复制功能的实现新版本的Redis使用Psync命令替代了Sync命令,可以同时实现全同步和部分同步。复制偏移量执行复制的两方,主从服务器,都会维护一个复制偏移量:主服务器每次向从服务器同步N个字节的数据,它都会修改自己的复制偏移量+N。从服务器每次从主服务器同步N个字节的数据,都会修改自己的复制偏移量+N。Replicationbacklogbuffer主服务器内部维护一个固定长度的先进先出队列作为replicationbacklogbuffer,其默认大小为1MB。当主服务器进行命令传播时,它不仅会将写命令同步到从服务器,还会将写命令写入复制积压缓冲区。服务器运行ID每个Redis服务器都有自己的运行ID,由服务器启动时自动生成。主服务器会将自己的运行ID发送给从服务器,从服务器保存主服务器的运行ID。从服务器Redis断开重连同步时,根据运行ID判断同步进度:如果从服务器上保存的主服务器运行ID与当前主服务器运行ID一致,则认为本次断线重连成功。是之前复制的master,master可以继续尝试部分同步操作。否则,如果两个主服务器的运行ID不同,则认为全量同步过程完成。psync命令流程有了前面的准备,我们开始分析psync命令的流程:如果从服务器之前没有复制过任何主服务器,或者之前执行过slaveofnoone命令,那么从服务器会向主服务器发送psync服务器?-1命令请求主服务器进行全量数据同步。否则,如果从服务器之前已经同步过一些数据,则从服务器向主服务器发送psync命令,其中runid是上一个主服务器的runningid,offset是当前从服务器的复制偏移量。主服务器收到前两种情况的psync命令后,会出现以下三种可能:其中,runid为当前主服务器的运行id,offset为当前主服务器的复制偏移量。如果主服务器响应+continue,则表示主服务器和从服务器进行了部分数据同步操作,只需要从从服务器同步丢失的数据即可。如果主服务器返回-err,说明主服务器版本低于2.8,无法识别psync命令。此时从服务器会向主服务器发送Sync命令,进行一次完整的全量数据同步。哨兵机制概述Redis使用哨兵机制来实现高可用。大致的工作原理是:Redis使用一组哨兵(Sentinel)节点来监控主从Redis服务的可用性。一旦发现Redis主节点失效,就会选举一个哨兵节点作为领导者(Leader)。然后哨兵***从剩余的Redis从节点中选出一个Redis节点作为新的Redis主节点对外服务。上面将Redis节点分为两类:哨兵节点(Sentinel):负责监控节点的运行。数据节点:即正常服务客户端请求的Redis节点,分为master和slave。以上就是大概的流程,这个流程需要解决以下几个问题:如何监控Redis数据节点?如何判断一个Redis数据节点失效?如何选择一个Sentinel***节点?依据是什么?让我们一一回答这些问题。三个监控任务Sentinel节点通过三个定时监控任务监控Redis数据节点的服务可用性。①info命令每隔10秒,每个sentinel节点都会向主从Redis数据节点发送info命令,获取新的拓扑信息。Redis拓扑信息包括:节点角色:master或slave。主从节点的地址和端口信息。这样sentinel节点可以自动从info命令中获取slave节点信息,这样后面添加的slave节点信息就可以自动感知到,不需要显式配置。②同步信息到__sentinel__:hello通道每个sentinel节点每隔2秒将自己获取的master节点信息和当前sentinel节点的信息同步到Redis数据节点的__sentinel__:hello通道。由于其他哨兵节点也订阅了这个通道,所以这个操作实际上可以在哨兵节点之间交换主节点和哨兵节点的信息。这个操作实际上完成了两件事:发现新的哨兵节点:如果有新的哨兵节点加入,此时保存新哨兵节点的信息,然后与哨兵节点建立连接。交换主节点的状态信息,作为后续客观判断主节点下线的依据。③对数据节点做心跳检测每个sentinel节点每隔1秒向master、slave数据节点和其他sentinel节点发送Ping命令进行心跳检测。这个心跳检测是后续主观判断数据节点下线的依据。主观下线和客观下线①主观下线以上三个监控任务中的第三个检测心跳任务,如果在配置的down-after-milliseconds后没有收到有效回复,则认为该数据节点“主观下线”。线(sdown)”。为什么叫“主观下线”呢?因为在分布式系统中,有多台机器协同工作,网络中可能会出现各种情况,仅靠一个节点的判断不足以认为一个数据节点下线,这需要下面的“目标下线”。②客观下线当一个哨兵节点主观认为主节点下线时,该哨兵节点需要通过“sentinelis-master-down-byaddr”命令向其他哨兵节点询问主节点是否下线,如果超过半数sentinel节点都已经响应下线了,此时master节点可以认为是“客观下线”了。选举哨兵***当主节点客观下线时,需要选举一个哨兵节点作为哨兵***,完成后续选举新主节点的工作。本次选举的总体思路是:每个sentinel节点通过向其他sentinel节点发送“sentinelis-master-down-byaddr”命令申请成为sentinel***。当每个sentinel节点收到“sentinelis-master-down-byaddr”命令时,只允许投票给第一个节点,其他节点的命令将被拒绝。如果一个Sentinel节点获得超过一半的同意票,它就成为一个Sentinel***。如果前三步在一定时间内没有选出哨兵***,则重新开始下一次选举。可以看出选举leader的过程和Raft中选举leader的过程非常相似。选择一个新的主节点在剩余的Redis从节点中,按照以下顺序选择一个新的主节点:过滤掉“不健康”的数据节点:比如主观下线、断开连接的从节点、五秒内没有回复的节点sentinelnodeping命令,和master节点失去联系的slave节点。选择Slave-Priority(从节点优先级)***的从节点,存在则返回,不存在则继续下面的流程。选择replicationoffset为***的slave节点,说明这个slave节点上的数据是最完整的。如果存在,它将返回。如果不存在,则继续下面的过程。此时,剩余的所有slave节点状态相同,选择runid最小的slave节点。新的主节点被提升并选出新的主节点后,需要最新的流程让该节点成为新的主节点:Sentinel***对上一步选中的从节点发出“slaveofnoone”命令使节点成为主节点。哨兵***向剩余的从节点发送命令,使它们成为新主节点的从节点。哨兵节点集合会将原来的主节点更新为从节点,并命令其在恢复时复制新主节点的数据。作者:codedump简介:codedump.info博主,从事互联网服务器后台开发多年。访问作者的博客https://www.codedump.info获取更多文章。
