redis源码浅析--十四.多机数据库的实现(一)--新老版本复制功能的区别与实现原理

环境说明:redis源码版本 5.0.3;我在阅读源码过程做了注释,git地址:https://gitee.com/xiaoangg/redis_annotation
如有错误欢迎指正
参考书籍:《redis的设计与实现》

文章推荐:
redis源码阅读-一--sds简单动态字符串
redis源码阅读--二-链表
redis源码阅读--三-redis散列表的实现
redis源码浅析--四-redis跳跃表的实现
redis源码浅析--五-整数集合的实现
redis源码浅析--六-压缩列表
redis源码浅析--七-redisObject对象(下)(内存回收、共享)
redis源码浅析--八-数据库的实现
redis源码浅析--九-RDB持久化
redis源码浅析--十-AOF(append only file)持久化
redis源码浅析--十一.事件(上)文件事件
redis源码浅析--十一.事件(下)时间事件
redis源码浅析--十二.单机数据库的实现-客户端
redis源码浅析--十三.单机数据库的实现-服务端 - 时间事件
redis源码浅析--十三.单机数据库的实现-服务端 - redis服务器的初始化
redis源码浅析--十四.多机数据库的实现(一)--新老版本复制功能的区别与实现原理
redis源码浅析--十四.多机数据库的实现(二)--复制的实现SLAVEOF、PSYNY
redis源码浅析--十五.哨兵sentinel的设计与实现
redis源码浅析--十六.cluster集群的设计与实现
redis源码浅析--十七.发布与订阅的实现
redis源码浅析--十八.事务的实现
redis源码浅析--十九.排序的实现
redis源码浅析--二十.BIT MAP的实现
redis源码浅析--二十一.慢查询日志的实现
redis源码浅析--二十二.监视器的实现

复制功能相关概念&搭建方法可以参考:https://blog.csdn.net/qq_16399991/article/details/99881319

目录

一  旧版复制功能

1.1.同步

1.2.命令传播

1.3.旧版复制功能的缺陷

二.新版复制功能

2.1.部分重同步实现

2.1.1复制偏移量

2.1.2 复制积压缓冲区

2.1.3 服务器运行ID


一  旧版复制功能

名词解释

redis复制功能分为 同步(sync)和命令传播(command propagate)两个操作;

  • 同步(sync):将slave数据库状态更新至master所处的数据状态;(全量操作)
  • 命令传播(command propagate):当master执行写命令,导致主从数据不一致时。将写命令传播到slave,从而达到一致状态;

1.1.同步

当slave接受到salveof命令,从服务首先同步操作,即像master发送SYNC命令,执行流程如下:

  1. slave向master发送SYNC命令;
  2. master收到SYNC命令后执行BGSAVE命令,在后台生成RDB文件,并用一个缓冲区记录从现在开始的所有写命令;
  3. master的BGSAVE执行完毕后,master将生成的RDB文件发送给slave;
  4. slave收到RDB文件后,将数据重做到slave中;
  5. master将步骤2中缓冲区记录的命令发送给salve。从而达到master和slave数据一致;


1.2.命令传播

同步完成后,当maser再次执行写命令,还会导致master和slave数据的不一致;

为了让master和slave数据保持一致,master在执行写命令时,master会将写命令发送给slave,slave执行写命令后,使master和slave数据保持一致;

 

1.3.旧版复制功能的缺陷

先看一个复制功能完整例子:

时间masterslave 
T0服务启动 同步
T1

执行命令
SET k1 v1;

SET k2 v2;

SET k3 v3:

 
T3 服务启动;
T4 向master发送SYNC命令;
T5

接受到了SYNC命令;执行BGSAVE;

 
T6

BGSAVE还没执行完毕;

执行命令

SET k4 v4;

SET k5 v5;

这时k4和k5记录到了缓冲区;

 
T7

BGSAVE命令执行完毕,这时生成的RDB文件包含k1,k2和k3;

将RDB文件发送给slave

 
T8 slave接受到RDB,重做;slave获得k1 k2 k3
...将 缓冲区中 set k4 v4 ;set k5 v5 发送给slave; 
.... 

接受到 set k4 v4 ;set k5 v5;

   (这时同步完成 数据一致);
T99

set k6 v6;

......

set k100000 v100000;

发送到slave 

接受master

set k6 v6;

.....

set k10000 v10000

命令传播
T100 假设salve因为网络原因与master断开连接;

断线重新复制

T101

set kk1 vv1;
set kk2 vv2;

set kk3 vv3;

掉线中...

掉线中...
掉线中...

T102 上线;
向master发送SYNC,
T103BGSAVE 
.....
发送RDB
 
T104 

重做RDB
....

 

 

 

 

在时间T100,slave因为网络原因与master断开了连接;

时间T102,slave重新连接上了master,这时master和slave数据已经不一致了。(但是只有 set kk1 vv1, set kk2 vv2 set kk3 vv3 不一致;)

slave发送SYNC命令,让master 和slave再次回到一致状态;

但是仔细研究这个断线 重新复制的过程,发现BGSAVE和传送RDB的过程并不是必做不可的。

因为这时只有KK1 KK2 KK3是不一致的。而RDB中k....k10000 都是不必要的;

SYNC命令事一个非常耗费资源的操作

  1. BGSAVE生成RDB文件会耗费大量CPU、内存、磁盘I/O资源;
  2. RDB文件传输给slave会消耗大量的网络资源(带宽和流量);
  3. slave接受RDB文件,载入期间 从服务器会堵塞,无法接受命令请求;

 

二.新版复制功能

为了解决旧版处理断线重复复制的低效问题。redis从2.8使用PSYNC来替代SYNC命令;

名词解释

  • 完整同步(full resynchronization):完整重同步执行和SYNC执行步骤基本一致
  • 部分重同步(partial resynchronization):部分重复制用于处理断线后重复复制状况;当slave断线后重新连接主服务器时,如果条件允许(什么条件:下边的2.1.2 复制积压缓冲区有介绍),主服务器可以将断线期间的命令发送给slave。 (上例子中将会只发送kk1 kk2 kk3 给slave,节省很多资源)

举个例子:

时间masterslave 
.................
T100 假设salve因为网络原因与master断开连接;

断线重新复制

T101

set kk1 vv1;
set kk2 vv2;

set kk3 vv3;

掉线中...

掉线中...
掉线中...

T102 上线;
向master发送PSYNC
T103像slave 发送+CONTINUE回复,表示执行部分重同步 
T104 

接受+CONTINUE回复,执行部分重同步

 

 向slave发送set kk1 vv1, set kk2 vv2, set kk2 vv3  
  接受 set kk1 vv1。 

2.1.部分重同步实现

重要概念

  • 复制偏移量
  • master 复制积压缓冲区
  • 服务器运行ID

2.1.1复制偏移量

master和slave都维护了一个复制偏移量;

master每次向slave发送N个字节数据时,master的偏移量就会加上N;

同理 slave每次接收到master的N个字节数据时,slave的偏移量也会加上N;

如果master和slave的偏移量是相同的,那么主从数据处于一致的状态;

举个例子
1.master和slave的偏移量都是10086(这时数据是一致的):

2.这时候master向slave发送了33个字节,并且三个slave都正常接受到了;偏移量加33变成了10119;

如果master和slave的偏移量是不同的,那么主从数据不一致;

举个例子

slave A断线,导致slave A没有接受到mater发送的33个字节数据;

这时 maser的偏移量变成了10119 ,slave A的因为没有接受到数据 偏移量并没有加33。master和slave数据不一致;

 

2.1.2 复制积压缓冲区

复制积压缓冲区是主服务器维护的一个固定长度的的队列(先进先出 默认1MB);

当master向slave传播命令时,会将命令写入到复制积压缓冲区

因此复制积压缓冲区记录了最近向slave传播的命令;并且为每个字节记录了相应的复制偏移量(这很重要);

当slave断线后重新连接master时,向master发送PSYNC命令 会将自己的复制偏移量发送给master。

master会根据这个偏移量决定对slave执行部分同步还是完全同步;

  • slave的偏移量在复制积压缓冲区,执行部分同步 ;
  • slave的偏移量不在复制积压缓冲区,则执行完成同步;

 

2.1.3 服务器运行ID

每个服务器都有自己的运行id,不论主从;

slave对master初次复制时,会保存master的运行id;

当slave重新连接到master时,slave向master发送之前保存的mater run id;

如果slave保存的master run id和重新连接的master run id不一致,(换了master),则执行完全同步;

相反,如果一致则尝试执行部分同步;

 

。。。。。。。

了解基础原理后,后面详细介绍代码的实现过程。。。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值