百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Redis 攻略面经-- 详解主从复制中的同步数据

mhr18 2024-10-26 10:47 54 浏览 0 评论

引言

Redis的特性就是必须支撑读高并发的,单节点Redis并发能力虽然不错,但是在高并发场景下也顶不住,且单节点如果宕机了,就会导致服务不可用。因此就有了主从这样的架构模式,给master去,数据同步给它的小弟slave去读写分离),这样请求就可以分发在多个Redis结点上了,同时也方便了水平扩容

所有的数据修改只发生在主服务器上,然后将最新的数据同步给从服务器上,以保证主从服务器的数据是一致,当然这只是我们从整体上来看,具体是如何做到主从数据一致性的我们下面来看看:


全量同步

当我们进行第一次同步,例如:服务器A和服务器B两个服务器,在服务器B执行:

replicaof <服务器 A 的 IP 地址> <服务器 A 的 Redis 端口号>
复制代码

那么此时服务器B就是服务器A的从结点了,那么服务器A就需要把数据同步给服务器B,由于是第一次同步,因此是全量同步,也就是把所有的数据都传给服务器B

那么服务器A如何判断是第一次同步呢?

在执行replicaof命令后,从服务器B就会给主服务器A发送psync指令,表明要进行数据同步,而psync命令有两个参数:

  • Replication Id:数据集的标记,主从结点的数据集一致,也就是说replication id相等
  • offset:偏移量,表示复制的进度,如果从节点的offset落后于主节点的,就代表从节点的数据落后于主节点,需要数据更新,通过主从结点的偏移量的差值也能知道需要更新哪一段数据

对于第一次同步的服务器B来说,并没有主服务器的replication id,且没有进行过复制,因此发送的命令为:psync ? -1

主服务器会根据从服务器发送的命令来判断下一步的操作,针对于psync ? -1,主服务器会返回FULLRESYNC {replication id} {offset}

  • FULLRESYNC:表明此次同步为全量同步
  • Replication Id:主结点的数据集,这样主节点和从节点的数据集Id就一致了
  • offset:表明此次从节点复制的数据的偏移量

上述的操作可以用下图来表示:


在建立完连接并协商好要传输的数据之后,就要开始正式传输数据了:

主服务器会执行bgsave在后台生成RDB快照,然后传输给从节点,从节点拿到数据后,清空当前结点的所有数据,然后导入RDB文件:


在服务器B导入 RDB 快照期间,客户端对服务器A的写操作,这部分数据服务器B并没有,那么Redis怎么解决这里的主从不一致呢?

主服务器会把:主服务器生成RDB文件期间主服务器发送RDB文件期间从服务器加载RDB文件期间,三个时间段的数据更改写入replication buffer缓冲区中

然后在从服务器RDB文件加载结束后,会发送一个确认的消息给主服务器,主服务器就会把缓冲区里面所有记录的写操作发送给从服务器,从服务器执行缓冲区中的操作,便主从数据一致了。


至此,第一次全量同步结束,完成第一次同步之后,主从结点之间就会建立一个TCP连接,后续的写操作的命令传播就靠这个长连接的TCP连接


增量同步

在第一次同步之后,主从结点通过TCP连接来进行通信写命令,可是由于网络波动,TCP连接断开了,重连后,中间的那部分数据会不会丢失呢?

如果说重连之后,要进行一次全量复制重新建立TCP连接,那么这个开销太大了,这就要提到增量同步。我们在讲psync命令的时候提到了两个个变量offset,在重连的时候,psync命令中的replication id是已知的,因此完整的命令就是:

fsync <replication id> <offset>
复制代码

然后主服务器发现replication id相同,offset大于从服务器,因此发送给从服务器CONTINUE,表明接下来使用增量同步

offset 和 数据的关系记录在哪呢?

主服务器进行命令传播的时候,不仅会把写命令发送给从服务器,还会把命令写到缓冲区repl_backlog_buffer中,因此这个缓冲区中会保存最近传播的写命令。

很明显,我们不可能缓冲所有的写命令,毕竟空间有限,也就是说只会缓存一定量的写命令,这是通过环形缓冲区来实现的:

也就是说,当缓冲区写满后,最旧的数据会被最新的数据所覆盖,那么就存在这个风险:网络恢复的时候,从服务器想读的数据已经被覆盖了,此时主服务器就会不得已采用全量同步,因此我们最好把缓冲区的大小设置的大一些

综上,全量同步的大概流程就是:

  1. 从服务器发送replication idoffset
  2. 主服务器根据这两个判断是否进行增量同步: replication id:首先判断是否是同一个数据集 offset: 如果说从服务器想读的数据已经被覆盖了,那就进行全量同步 如果数据还在,就把offset差值的数据传给从服务器,在此期间replication buffer缓冲区也会记录在此期间主服务器进行的写操作命令,在增量同步结束之前把replication buffer中的命令发送给从服务器

主-从-从链式结构

在前面的分析中我们可以发现,主节点在主从同步的时候所做的比较耗时的两个操作就是:生成RDB快照、传输RDB快照:

  • 生成RDB快照:尽管我们使用的是bgsave后台生成RDB快照,但是如果数据量比较大,那么尽管是后台执行,也有可能影响到主线程的效率甚至阻塞,导致主线程挂掉
  • 传输RDB快照:传输RDB文件会占用主服务器的网络带宽,会影响主服务器响应命令请求

因此我们可以限制一个master上的slave结点个数,如果实在太多slave,则可以采用主-从-从链式结构,减少master压力:

也就是说数据同步不一定需要主节点“亲力亲为”,可以选个“副总”帮助去做数据同步


主从数据不一致

主从结点之间的写命令发送是异步的,也就是说:

  • 客户端发送写命令
  • 主服务器执行写命令,并异步把写命令发送给从服务器
  • 主服务器执行完写命令就会把结果返回给客户端
  • 并不会等待从服务器执行完命令再返回结果给客户端
  • 在从服务器还没有执行主服务器发送过来的命令时,去读取就会有主从结点的数据不一致。 也就是说无法实现主从数据时刻保持一致,也就是强一致性,除非进行同步,但是同步会很影响效率。

那我们如何去处理这种主从数据不一致的情况呢?

  1. 硬件的角度:保证主从结点间通信状况,保证网络连接状况良好
  2. 软件的角度:我们可以自己弄一个检测程序,来检测主从结点的数据差 通过Redis的INFO replication拿到主从结点的offset,得到他们的差值 对于差值大于我们指定的差值的时候,就让客户端不与这个结点通信

主从切换的数据丢失

异步复制同步丢失

在前文中我们提到,Redis主从结点之间的数据复制,是异步复制的,也就是说可能存在:

  • 主服务器存在很多写命令没有传给从服务器,数据同步需要比较久的时间
  • 然后客户端发送写命令
  • 主服务器执行完写命令
  • 返回结果给客户端
  • 但是主服务器返回给客户端结果后和同步数据前,发生了Redis宕机,那么数据就会丢失

那我们如何尽可能的去减少数据丢失呢?

Redis配置中有个参数min-slaves-max-lag,Redis会根据当前数据同步的速度,判断出同步完成需要的时间,如果时间超过了min-slaves-max-lag,便不再接受客户端的请求,这样即使丢数据,也只会丢这10s内的数据

那么总不能为了宕机这种特殊情况,一直不处理请求,此时我们可以把数据线丢进本地缓存或者磁盘或者消息队列,这样等待Redis恢复正常,再去读取这些消息即可。


集群脑裂

如果主节点的网络失联,与所有的从节点都失联了,但是客户端并不知情,数据还是在往这个结点传,这些数据都写在了主节点的缓冲区中,此时,哨兵发现了主节点失联了,于是选出了另外一个主节点,此时就出现了所谓的:集群脑裂——此时集群有两个主节点

然后原主节点的网络好了,但是由于哨兵机制,现在原主节点降级为从节点,会与现主节点做一次全量同步,这样在主节点网络失联期间的数据就丢失了

那我们如何去减少集群脑裂丢失的数据呢?

在Redis的配置文件中有两个参数帮助我们解决问题:

  • min-slaves-to-write:主节点至少有x个从节点,否则主结点禁止写数据
  • min-slaves-max-lag:主从复制的延迟不能超过x秒,否则主节点禁止写数据

主节点连接的从节点中至少有 x 个从节点,并且主节点进行数据复制时的 ACK 消息延迟不能超过 x 秒,原主节点就会被限制接收客户端写请求,客户端也就不能在原主节点中写入新数据了


总结

本文讲了Redis主从复制进行数据同步的原理、数据不一致或者丢失的情况以及解决办法

  • 对于主从复制的同步数据,我们分别介绍了: 第一次同步时进行的全量复制 第一次同步结束后命令传播的方式 增量复制的使用情况以及使用流程
  • 对于数据的丢失和不一致,我们分别介绍了: 主从数据由于异步复制导致无法保证强一致性 如何减少主从数据不一致带来的影响 异步复制同步丢失集群脑裂 带来的数据丢失问题 相信读完今天的文章,大家能对Redis集群的底层原理有了更深一步的理解~



原文链接:https://juejin.cn/post/7174625638056198200

相关推荐

【预警通报】关于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版本的核...

取消回复欢迎 发表评论: