面试官:聊聊Redis如何用主从复制模式 实现高可用
mhr18 2024-11-07 11:04 26 浏览 0 评论
作者:绘你一世倾城 链接:https://juejin.im/post/5e755f0d518825490e458453
之前总结过redis的持久化机制:深度剖析Redis持久化机制,持久化机制主要解决redis数据单机备份问题;redis的高可用需要考虑数据的多机备份,多机备份通过主从复制来实现,这是redis高可用的基石。本文将详细介绍redis主从复制的实现原理,在使用过程中应该注意的问题和相关配置。
1. CAP理论
CAP理论是分布式领域的牛顿定律,所有的分布式存储中间件都要使用它作为理论基石。如下图所示:
这个原理很简单,首先明确几个概念:
- C : Consistent, 一致性
- A : Availability, 可用性
- P : Partition tolerance, 分区容忍性
分布式系统的节点往往分布在不同的机器上,它们之间由网络进行隔离,当网络断开时就会产生网络分区。网络分区不可避免,但是当网络分区发生时,对分布式系统中一个节点的修改操作无法同步给其它节点,数据一致性也就无法满足;想要满足一致性,除非牺牲可用性,也就是暂停分布式节点服务,等到网络恢复,数据一致后,再对外提供服务。分布式系统中网络分区不可避免,一致性和可用性水火不容。这就是cap理论:网络分区发生时,一致性和可用性两难全。
2.redis主从复制
2.1 概述
互联网圈经常谈“三高”架构:高并发、高性能、高可用。对于redis来说,高并发、高性能可以保证,高可用需要架构的设计,单机redis由于存在系统崩溃、硬盘故障的风险,还有内存的限制,所以企业一般都会搭建主从,对系统有更高要求会搭建集群。
为了保持数据一致性,主节点(master)只写,从节点(slave)只读,数据由主节点复制给从节点,这个复制的过程就是主从复制。
redis的主从复制是异步的,分布式的redis系统并不满足一致性要求,但是在网络断开的情况下,主节点依然可以对外提供服务,满足可用性。redis保证最终一致性,从节点会努力追赶主节点,最终从节点的状态会和从节点保持一致。网络断开的情况下,主从节点数据会出现大量的不一致,但一旦网络恢复,从节点会继续追赶主节点,最终达到和主节点状态一致。
为了减轻redis主节点的同步负担,redis 的后续版本还增加了从从同步,与此同时,数据一致性会变差。
2.2 主从复制的作用
主从复制在服务中起到了什么效果呢?
- 读写分离:master写,slave读,提高服务器的读写负载能力。
- 负载均衡:基于主从架构,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数量,通过多个从节点分担数据读取负载,大大提高redis服务器并发量和数据吞吐量。
- 故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复。
- 数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式。
- 高可用基石:基于主从复制,构建哨兵模式与集群,实现redis的高可用方案。
2.3 怎样配置实现主从复制?
有三种配置实现redis的主从:
- 方式一:客户端发送命令
slaveof <masterip> <masterport>
复制代码
- 方式二:启动服务器时添加参数
redis-server -slaveof <masterip> <masterport>
复制代码
- 方式三:服务器配置文件中配置(通过redis.conf)
slaveof <masterip> <masterport>
复制代码
比较主流的用法是通过配置文件的方式实现主从。还有其它的一些命令:
- 主从断开连接,可以从客户端发送命令
slaveof no one
复制代码
- 服务端设置了授权访问
#master有两种方式设置
//-- 1.master配置文件中设置
requirepass <password>
//-- 2.master客户端发送命令设置密码
config set requirepass <password>
config get requirepass
#slave有三种方式实现认证
//-- 1.客户端发送命令设置密码
auth <password>
//-- 2.slave配置文件设置密码
masterauth <password>
//-- 3.启动客户端设置密码
redis-cli -a <password>
复制代码
2.4 redis主从复制的工作流程
redis主从复制实现过程有三个阶段:
建立连接、数据同步、命令传播。建立连接阶段主从节点建立通信的桥梁,彼此之间同步一些基础信息;数据同步阶段实现从节点全量同步主节点的数据;从节点同步完主节点数据之后,就进入了命令传播阶段,主节点接收写请求,数据不断发生变化,通过命令传播阶段主节点将数据源源不断的同步给从节点。下边我们详细介绍主从复制这三个阶段的工作细节和注意事项。
2.4.1 建立连接阶段
建立slave到master的连接,使master能识别slave, 并保存slave的端口号;与此同时,slave也保存master的地址和端口号信息。
- slave发送slaveof ip port命令给master,master响应slave
- slave保存master的ip和端口号,建立socket连接
- 在socket连接之上,主从节点实现了心跳机制,这部分内容也比较重要,后边会提到。
- 如果有认证机制,从节点通过上边说到的认证指令,发送认证信息给master,实现认证。
- 从节点将自己的端口信息发送发送给主节点,主节点保存。
通过以上过程主从之间的连接就建立了。
2.4.2 数据同步阶段
数据同步阶段实现的功能是从节点从主节点同步全量的数据。这个过程又分为几个小阶段,最主要的就是数据的全量复制和部分复制, 对应的流程就是主节点发送rdb文件同步数据和发送缓冲区写命令(aof)同步数据给从节点。下图是实现细节:
- 首先slave节点先发起命令psync ? -1,向master节点要全量数据。
- master节点接收到指令以后,执行bgsave,将当前内存数据快照保存为rdb文件,这个过程为了不影响主节点继续对外提供服务,采用了Copy On Write技术。与此同时,master节点也会将bgsave保存快照期间接收到的写更新命令添加到复制挤压缓冲区当中。master节点rdb文件生成完毕以后,会通过第一阶段建立的socket连接将它发送给slave节点,还会发送+FULLRESYNC runid offset给slave节点,告诉slave节点自己的runid和offset。
什么是runid?
redis-server在每次启动的时候都会生成一个runid,因为redis-server是一个守护进程,所以在运行期间,runid不会发生变化,可以通过info server指令查看runid,它是一个40位字符长度的字符串。上文提到的psync有两个参数,和+FULLRESYNC一样:psync <runid> <offset>;runid的意义是什么呢?当master节点发生故障发生了变更后,在接到slave的指令以后,对比参数中的runid如果和自己的runid不一致,就会再次进行全量复制,因为换主了。
什么是复制挤压缓冲区和offset?
复制挤压缓冲区是一个先进先出(FIFO)的环形队列,用于存储服务端执行过的命令,每次传播命令,master节点都会将传播的命令记录下来,保存在这里。
复制挤压缓冲区由两部分组成:偏移量和字节值。字节值是redis指令字节的存储(redis指令以一种Redis序列化文本协议的格式存储),偏移量offset就是当前字节值在环形队列中的偏移量。
- slave节点接收完master节点同步的rdb文件之后,将rdb的内容加载到自己的内存,然后将master节点的runid和offset记录下来。
- 有了master节点的runid和offset,在加载完rdb文件之后,就开始向master节点发送新的命令psync runid offset,向master节点要新数据。新数据是master节点在bgsave生成rdb文件时和向slave同步数据的这段时间产生的,所以这段时间的工作也称为部分复制。
- master节点收到slave节点发送的请求数据命令之后,会检查runid是否一致(是否换主),offset是否一致(因为复制挤压缓冲区是定长的,所有有可能会溢出),这两个条件只要有一个不满足,master就会向slave再次全量的同步数据(读者可能会发现,如果master节点写并发很高,复制挤压缓冲区又设置的比较小的话,可能会每次向slave同步完数据以后,每次复制挤压缓冲区都会溢出,造成主从之间循环的全量复制。这确实是应该规避的问题!我们后边会针对主从复制应该考虑的问题做一个总结)。在runid和offset都满足的情况下,master节点就会向slave节点发送指令+CONTINUE offset,接着从offset位置开始同步数据,数据都在主节点的复制挤压缓冲区中了,所以直接复制发送就可以了。
- slave节点接收到master节点发送的+CONTINUE offset指令之后,更新自己保存的offset值,然后将从master节点同步过来的数据,使用bgrewriteaof,重放aof数据。
到这里,主从复制的第二阶段:数据同步阶段工作就完成了。
2.4.3 命令传播阶段
命令传播阶段类似于数据同步阶段的部分复制,当master节点数据被修改以后,就和slave节点的数据不一致了,这个时候master节点就会根据slave上报的offset开始传播数据(一主多从的架构中,master节点要记录每一个slave的offset)。slave接收到数据以后,执行bgrewriteaof重放数据。在这个工作过程中,如果因为网路问题导致offset溢出或者换主的情况,主从之间还是会进行数据的全量同步的。
2.5 心跳机制
进入命令传播阶段以后,master节点与slave节点需要进行信息传递,使用心跳机制进行维护,实现双方保持在线。
master节点心跳使用指令PING,由配置repl-ping-slave-period决定,默认10秒,作用是判断slave是否在线,可以通过info replication获取slave最后一次连接到现在的时间间隔,lag的值维护在0和1视为正常。
slave节点的心跳任务使用指令REPLCONF ACK {offset},周期是1秒,slave的心跳任务有两个作用:
- 汇报自己的offset给master,这在数据传播起到了关键性作用,因为master节点向slave节点传播数据,offset是一项非常重要的指标。
- 判断master是否在线
在心跳阶段应该注意:当slave节点多数掉线,或者延迟过高时,master节点为了保证数据的稳定性,将拒绝所有信息的同步。有如下配置:
min-slaves-to-write 2
min-slaves-max-lag 8
复制代码
上述配置含义是:当slave数量小于2个,或者所有的slave的延迟都大于等于8秒时,强制关闭master写功能,停止数据同步。
3.主从复制常见问题
上边介绍的主从复制是建立在主从节点间的网络和服务都正常的情况下,业务场景中要考虑更多的实际情况。
3.1 master重启
伴随着系统的运行,master节点的内存数据量变得很大的情况下,一旦master节点重启,runid将发生变化,会导致slave的全量复制操作。
这里有一个优化方案:在master节点内部创建master_replid变量,使用runid相同的策略生成,长度41位,发送给所有的slave节点。在master节点关闭时,执行命令shutdown save,进行RDB的数据持久化,将runid与offset保存在RDB文件中。在RDB文件中有了repl-id和repl-offset信息以后,通过指令redis-check-rdb命令可以查看这些信息。在master节点重启后,将RDB文件加载到内存中以后,也会将repl-id和repl-offset加载到内存中。通过info 指令可以查看:
master_repl_id = repl
master_repl_offset = repl-offset
复制代码
作用是:master节点重启之后会保存原来的runid,重启后恢复该值,会让所有的slave节点认为还是之前的master节点。
3.2 复制积压缓冲区太小
当复制积压缓冲区太小的时候,当master节点写并发很大,master节点和slave节点网络有抖动的时候,就会导致数据同步不及时,造成offset溢出,进而导致全量复制。这个时候,我们可以考虑修改复制积压缓冲区的大小,由配置repl-backlog-size控制。设置多大比较合适呢,这要根据master的并发量和网络情况做具体的评估。
3.3 slave执行了keys * 、hgetall等命令
前边内容我们提到slave节点每秒都会发送REPLCONF ACK指令到master节点,master节点调用复制函数relicationCron()同步数据给slave节点时,如果slave节点执行了keys *、hgetall等阻塞命令的时候,就会在很长一段时候得不到响应。这就会导致master的各种资源(输出缓冲区、带宽、连接)等被占用。master节点的CPU就会变高,slave频繁的断开连接。
解决方案是master节点通过配置:repl-timeout设置合理的超时时间(默认60s),超过改值,master节点将释放slave节点。
3.4 master节点发送ping指令频度低,网络存在丢包
master节点默认10s向slave节点发送一次ping指令,因为master节点不仅要处理大量的写任务,还可能维护着多个master,所以ping设置的不太及时。但是当ping指令在网络中存在丢包时,master节点如果设置的超时时间太短,就会导致master节点与slave节点断开连接。
解决方案有:提高master节点ping的频度,超时时间repl-time设置为ping指令时间的5~10倍。
3.5 网络信息不同步,数据发送有延迟
当主从同步中网络数据发送有延迟的时候,就会造成多个slave获取到的数据不同步,解决方案是优化master节点和slave节点的网络环境,通常是放置在一个机房部署。另外要监控master和slave节点的延迟,如果延迟过大,可以暂时屏蔽对slave节点的访问。通过下面指令设置:
slave-serve-stale-data yes | no
复制代码
开启后,slave节点仅仅能响应info、slaveof等少数命令,除非对数据一致性要求很高,否则不要轻易这样使用。
4.总结
本文主要总结了redis实现主从复制的实现细节和注意事项。redis的主从复制是实现高可用的重要基石,后边的文章将总结哨兵和集群的搭建。
小福利:
通过合法手段,获取到一些极客付费课程 ,嘘~,免费 送给小伙伴们。评论【666】我会私信发你
相关推荐
- 【预警通报】关于WebLogic存在远程代码执行高危漏洞的预警通报
-
近日,Oracle官方发布了2021年1月关键补丁更新公告CPU(CriticalPatchUpdate),共修复了包括CVE-2021-2109(WeblogicServer远程代码执行漏洞)...
- 医院信息系统突发应急演练记录(医院信息化应急演练)
-
信息系统突发事件应急预案演练记录演练内容信息系统突发事件应急预案演练参与人员信息科参与科室:全院各部门日期xxxx-xx-xx时间20:00至24:00地点信息科记录:xxx1、...
- 一文掌握怎么利用Shell+Python实现完美版的多数据源备份程序
-
简介:在当今数字化时代,无论是企业还是个人,数据的安全性和业务的连续性都是至关重要的。数据一旦丢失,可能会造成无法估量的损失。因此,如何有效地对分布在不同位置的数据进行备份,尤其是异地备份,成为了一个...
- docker搭建系统环境(docker搭建centos)
-
Docker安装(CentOS7)1.卸载旧版Docker#检查已安装版本yumlistinstalled|grepdocker#卸载旧版本yumremove-ydocker.x...
- 基础篇:数据库 SQL 入门教程(sql数据库入门书籍推荐)
-
SQL介绍什么是SQLSQL指结构化查询语言,是用于访问和处理数据库的标准的计算机语言。它使我们有能力访问数据库,可与多种数据库程序协同工作,如MSAccess、DB2、Informix、M...
- Java21杀手级新特性!3行代码性能翻倍
-
导语某券商系统用这招,交易延迟从12ms降到0.8ms!本文揭秘Oracle官方未公开的Record模式匹配+虚拟线程深度优化+向量API神操作,代码量直降70%!一、Record模式匹配(代码量↓8...
- 一文读懂JDK21的虚拟线程(java虚拟线程)
-
概述JDK21已于2023年9月19日发布,作为Oracle标准Java实现的一个LTS版本发布,发布了15想新特性,其中虚拟线程呼声较高。虚拟线程是JDK21中引入的一项重要特性,它是一种轻量级的...
- 效率!MacOS下超级好用的Linux虚拟工具:Lima
-
对于MacOS用户来说,搭建Linux虚拟环境一直是件让人头疼的事。无论是VirtualBox还是商业的VMware,都显得过于笨重且配置复杂。今天,我们要介绍一个轻巧方便的纯命令行Linux虚拟工具...
- 所谓SaaS(所谓三维目标一般都应包括)
-
2010年前后,一个科技媒体的主编写一些关于云计算的概念性问题,就可以作为头版头条了。那时候的云计算,更多的还停留在一些概念性的问题上。而基于云计算而生的SaaS更是“养在深闺人未识”,一度成为被IT...
- ORA-00600 「25027」 「x」报错(报错0xc0000001)
-
问题现象:在用到LOB大对象的业务中,进行数据的插入,失败了,在报警文件中报错:ORA-00600:内部错误代码,参数:[25027],[10],[0],[],[],[],[],[...
- 安卓7源码编译(安卓源码编译环境lunch失败,uname命令找不到)
-
前面已经下载好源码了,接下来是下载手机对应的二进制驱动执行编译源码命令下载厂商驱动https://developers.google.com/android/drivers?hl=zh-cn搜索NGI...
- 编译安卓源码(编译安卓源码 电脑配置)
-
前面已经下载好源码了,接下来是下载手机对应的二进制驱动执行编译源码命令下载厂商驱动https://developers.google.com/android/drivers?hl=zh-cn搜索NGI...
- 360 Vulcan Team首战告捷 以17.5万美金强势领跑2019“天府杯“
-
2019年11月16日,由360集团、百度、腾讯、阿里巴巴、清华大学与中科院等多家企业和研究机构在成都联合主办了2019“天府杯”国际网络安全大赛暨2019天府国际网络安全高峰论坛。而开幕当日最激荡人...
- Syslog 日志分析与异常检测技巧(syslog发送日志配置)
-
系统日志包含有助于分析网络设备整体运行状况的重要信息。然而,理解并从中提取有效数据往往颇具挑战。本文将详解从基础命令行工具到专业日志管理软件的全流程分析技巧,助你高效挖掘Syslog日志价值。Gr...
- 从Oracle演进看数据库技术的发展(从oracle演进看数据库技术的发展的过程)
-
数据库技术发展本质上是应用需求驱动与基础架构演进的双向奔赴,如何分析其技术发展的脉络和方向?考虑到oracle数据库仍然是这个领域的王者,以其为例,管中窥豹,对其从Oracle8i到23ai版本的核...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle基目录 (50)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (53)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)