当前位置: 首页 > 科技观察

调研Redis的两种高可用方案

时间:2023-03-22 16:55:00 科技观察

介绍:Redis是应用广泛的基础软件之一。对于工程师、架构师、运维人员来说,了解Redis的高可用方案及其背后的原理是必备的基础知识。本文作者对Redis高可用的各个方面进行了深入剖析,并做了有效的总结,相信能对读者起到很好的引领作用。作者codedumpcodedump.info博主,从事互联网服务器后台开发多年。访问作者的博客阅读更多代码转储文章。Redis为了实现高可用性(HighAvailability,简称HA),采用了以下两种方式:主从复制数据。哨兵用于监视数据节点的运行。一旦主节点出现问题,从节点将继续服务。主从复制在Redis中,主从节点复制数据可以分为全量复制和部分复制。旧版本全量拷贝功能的实现全量拷贝使用snyc命令实现,过程如下:从服务器向主服务器发送sync命令。master收到sync命令后,调用bgsave命令生成最新的rdb文件,并将该文件同步到slave,这样slave加载rdb文件后,状态会和master保持一致服务器在执行bgsave命令时。主服务器将命令缓冲区中存储的写命令同步给从服务器,从服务器执行这些命令,使从服务器的状态与主服务器的当前状态一致。旧版本的全量复制功能最大的问题是,当从服务器断开重连时,即使从服务器上已经有部分数据,也需要全量复制,效率很低,所以新版Redis在这部分做了改进。新版本全量复制功能的实现新版本的Redis使用psync命令代替了sync命令,可以同时实现全同步和部分同步。复制偏移量执行复制的两方,主从服务器,会维护一个复制偏移量:主服务器每次向从服务器同步N个字节的数据,都会修改自己的复制偏移量+N。从服务器每次从master服务器同步N个字节的数据,它会修改自己的replicationoffset+N。ReplicationBacklogBuffermaster服务器内部维护一个固定长度的FIFO队列作为复制backlogbuffer,默认大小为1MB。当主服务器进行命令传播时,它不仅会将写命令同步到从服务器,还会将写命令写入复制积压缓冲区。服务器运行ID每个Redis服务器都有它的运行ID。运行ID是服务器启动时自动生成的。主服务器会将自己的运行ID发送给从服务器,从服务器保存主服务器的运行ID。与服务器Redis断连重连同步时,根据运行ID判断同步进度:如果从服务器上保存的主服务器运行ID与当前主服务器运行ID一致,则认为本次断线重连成功的是之前复制的master,master可以继续尝试partialsync操作。否则,如果前后两次主服务器运行ID不同,则认为全量同步完成。psync命令流程有了前面的准备,我们开始分析psync命令流程:如果从服务器之前没有复制过任何主服务器,或者之前执行过slaveofnoone命令,那么从服务器会向主服务器发送psync服务器?-1命令请求主服务器进行全量数据同步。否则,如果之前的从服务器同步过一些数据,则从服务器向主服务器发送psync命令,其中runid是主服务器上次运行的id,offset是复制偏移量当前的从属服务器。以上两种情况,主服务器收到psync命令后,会出现以下三种可能:主服务器返回+fullresync回复,表示主服务器需要与从属服务器。其中,runid为当前主服务器的运行id,offset为当前主服务器的复制偏移量。如果主服务器响应+continue,则表示主服务器和从服务器进行了部分数据同步操作,只需要从从服务器同步丢失的数据即可。如果主服务器返回-err,说明主服务器版本低于2.8,无法识别psync命令。此时从服务器会向主服务器发送sync命令,进行完整的全量数据同步。哨兵机制概述Redis使用哨兵机制来实现高可用性(HA)。它的大致工作原理是:Redis使用一组哨兵节点来监控主从redis服务的可用性。一旦发现Redis主节点失效,就会选举一个哨兵节点作为领导者(leader)。然后哨兵***从剩余的Redis从节点中选出一个Redis节点作为新的Redis主节点对外服务。上面将Redis节点分为两类:哨兵节点(sentinel):负责监控节点的运行。数据节点:即正常服务客户端请求的Redis节点,分为master和slave。以上是大致流程。这个过程需要解决以下问题:如何监控Redis数据节点?如何判断一个Redis数据节点是否发生故障?如何选择一个Sentinel***节点?哨兵节点选择新的Redis主节点的依据是什么?让我们一一回答这些问题。三个监控任务哨兵节点通过三个定时监控任务监控Redis数据节点的服务可用性。info命令每隔10秒,每个sentinel节点都会向主从Redis数据节点发送info命令,获取新的拓扑信息。Redis拓扑信息包括:节点角色:master或slave。主从节点的地址和端口信息。这样sentinel节点可以自动从info命令中获取slave节点信息,这样后面添加的slave节点信息就可以自动感知到,不需要显式配置。将信息同步到__sentinel__:hello通道每2秒,每个sentinel节点都会将自己的master节点信息和当前sentinel节点信息同步到Redis数据节点的__sentinel__:hello通道,因为其他sentinel节点也订阅了这个通道,因此其实这个操作,可以在哨兵节点之间交换主节点和哨兵节点的信息。这个操作实际上完成了两件事:*新哨兵节点的发现:如果有新的哨兵节点加入,此时保存新哨兵节点的信息,然后与哨兵节点建立连接。*交换主节点的状态信息,作为后续客观判断主节点下线的依据。对数据节点的心跳检测每1秒,每个sentinel节点向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命令,以及与主节点失去联系的从节点。选择slave-priority(从节点优先级)***的从节点,存在则返回,不存在则返回,继续下面的流程。选择replicationoffset为***的slave节点,说明这个slave节点上的数据是最完整的。如果存在,不存在则返回,继续下面的流程。此时,剩余的所有slave节点状态相同,选择runid最小的slave节点。新的主节点被提升并选出新的主节点后,需要最新的流程让该节点成为新的主节点:Sentinel***对上一步选中的从节点发出“slaveofnoone”命令使节点成为主节点。哨兵***向剩余的从节点发送命令,使它们成为新主节点的从节点。哨兵节点集合会将原来的主节点更新为从节点,并命令其在恢复时复制新主节点的数据。如果这个过程中哨兵***失败了怎么办?原文地址:https://www.codedump.info/post/20190409-redis-sentinel/参考阅读:主流微服务注册中心分析对比一张图看懂谷歌工具栈FacebookF4架构解读:千亿图片存储Haystack被视为Kafka替代者的MessageQueue的演变:ApachePulsar的简要设计