敞开生长之旅!这是我参与「日新方案 12 月更文挑战」的第十六天,点击检查活动详情
大家好,我是Zhan,一名个人练习时长一年半的大二后台练习生
这篇文章是复习 Redis 主从仿制同步数据原理 的学习笔记
假如有不对的当地,欢迎各位纠正
与君同舟渡,达岸各自归
导言
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中,因而这个缓冲区中会保存最近传达的写指令。
很明显,咱们不或许缓冲一切的写指令,毕竟空间有限,也便是说只会缓存一定量的写指令,这是经过环形缓冲区来完成的:
也便是说,当缓冲区写满后,最旧的数据会被最新的数据所掩盖,那么就存在这个危险:网络康复的时分,从服务器想读的数据现已被掩盖了,此刻主服务器就会不得已选用全量同步,因而咱们最好把缓冲区的大小设置的大一些
综上,全量同步的大概流程便是:
- 从服务器发送replication id 和 offset
- 主服务器依据这两个判别是否进行增量同步:
- replication id:首先判别是否是同一个数据集
-
offset:
- 假如说从服务器想读的数据现已被掩盖了,那就进行全量同步
- 假如数据还在,就把offset差值的数据传给从服务器,在此期间replication buffer缓冲区也会记载在此期间主服务器进行的写操作指令,在增量同步完毕之前把replication buffer中的指令发送给从服务器
主-从-从链式结构
在前面的剖析中咱们能够发现,主节点在主从同步的时分所做的比较耗时的两个操作便是:生成RDB快照、传输RDB快照:
- 生成RDB快照:虽然咱们运用的是bgsave后台生成RDB快照,可是假如数据量比较大,那么虽然是后台履行,也有或许影响到主线程的功率乃至堵塞,导致主线程挂掉
- 传输RDB快照:传输RDB文件会占用主服务器的网络带宽,会影响主服务器呼应指令恳求
因而咱们能够约束一个master上的slave结点个数,假如实在太多slave,则能够选用主-从-从链式结构,削减master压力:
也便是说数据同步不一定需要主节点“亲力亲为”,能够选个“副总”帮助去做数据同步
主从数据不共同
主从结点之间的写指令发送是异步的,也便是说:
- 客户端发送写指令
- 主服务器履行写指令,并异步把写指令发送给从服务器
- 主服务器履行完写指令就会把成果回来给客户端
- 并不会等待从服务器履行完指令再回来成果给客户端
- 在从服务器还没有履行主服务器发送过来的指令时,去读取就会有主从结点的数据不共同。 也便是说无法完成主从数据时刻保持共同,也便是强共同性,除非进行同步,可是同步会很影响功率。
那咱们怎么去处理这种主从数据不共同的状况呢?
- 从硬件的角度:确保主从结点间通讯状况,确保网络衔接状况良好
- 从软件的角度:咱们能够自己弄一个检测程序,来检测主从结点的数据差
- 经过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集群的底层原理有了更深一步的了解~
友链
- Redis 攻略面经(一)– 常见数据类型
- Redis 攻略面经(二)– 关于持久化,你了解多少?
- Redis 攻略面经(三)– 详解内存回收的两种策略
✒写在最后
都看到这儿啦~,给个点赞再走呗~,也欢迎各位大佬纠正以及补充,在评论区一起沟通,共同进步!也欢迎加微信一起沟通:Goldfish7710。咱们明天见~