十二、复制(Redis)

在Redis中,用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务 器去复制(replicate)另一个服务器,我们称呼被复制 的服务器为主服务器(master),而对主服务器进行复制 的服务器则被称为从服务器(slave)。

一、旧版复制功能的实现

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

同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态。

命令传播操作则用于在主服务器的数据库状态被修改,导致主从服务器的数据库状 态出现不一致时,让主从服务器的数据库重新回到一致状态。

1.1 同步

    将从服务器的数据库状态更新至主服务器当前所处的数据库 状态
    步骤 :
    1.从服务器向主服务器发送SYNC命令

    2.收到命令的主服务器执行命令,在后台生成一个RDB文件,并使 用一个缓冲区记录从现在开始执行的所有写命令

    3.当主服务器的BGSAVE命令执行完毕时,主服务器会将命令生成的RDB 文件发送给从服务器,从服务器接收并载人这个RDB文件,将自己的数据库状态更新至主 服务器执行叹命令时的数据库状态。

    4.主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写 命令,将自己的数据库状态更新至主服务器数据库当前所处的状态

1.2 命令传播

在同步操作执行完毕之后,主从服务器两者的数据库将达到一致状态,但这种一致并不是一成不变的,每当主服务器执行客户端发送的写命令时,主服务器的数据库就有可能会被 修改,并导致主从服务器状态不再一致

为了让主从服务器再次回到一致状态,主服务器需要对从服务器执行命令传播操作: 服务器会将自己执行的写命令,也即是造成主从 服务器不一致的那条写命令,发送给从服务器执 行,当从服务器执行了相同的写命令之后,主从 服务器将再次回到一致状态。

 

二、旧版复制功能的缺陷

在Redis中,从服务器对主服务器的复制可以分为以下两种情况:

初次复制:
    从服务器以前没有复制过任何主服务器,或者从服务器当前要复制的主 服务器和上一次复制的主服务器不同

断线后重复制:
    处于命令传播阶段的主从服务器因为网络原因而中断了复制,但从 服务器通过自动重连接重新连上了主服务器,并继续复制主服务器

对于初次复制来说,旧版复制功能能够很好地完成任务,但对于断线后重复制来说,旧 版复制功能虽然也能让主从服务器重新回到一致状态,但效率却非常低,因为断线重连后,从服务器会发送sync命令给主服务器,重新进行同步操作,这样会给主服务器和从服务器造成巨大的资源浪费

每次执行SYNC命令,主从服务器需要执行以下动作:
    主服务器需要执行BEGSAVE命令进行RDB生成RDB文件,但这会耗费服务器大量的CPU、内存和磁盘I/O资源
    主服务器需要将自己生成的RDB文件发送给从服务器,这个发送操作会耗费主 从服务器大量的网络资源(带宽和流量),并对主服务器响应命令请求的时间产生影响
    接收到RDB文件的从服务器需要载入主服务器发来的RDB文件,并且在栽入 期间,从服务器会因为阻塞而没办法处理命令请求

 

三、新版复制功能的实现

为了解决旧版复制功能在处理断线重复制情况时的低效问题,Redis从2.8版本开始, 使用PSYNC命令代替SYNC命令来执行复制时的同步操作

PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization) 两种模式:

完整重同步:
        完整重同步用于处理初次复制情况:完整重同步的执行步骤和命令的执 行步骤基本一样,它们都是通过让主服务器创建并发送RDB文件,以及向从服务器 发送保存在缓冲区里面的写命令来进行同步

部分重同步:
        部分重同步则用于处理断线后重复制情况:当从服务器在断线后重新连接主服务 器时,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送 给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务 器当前所处的状态

 

四、部分重同步的实现

部分重同步功能由以下三个部分构成:

主服务器的复制偏移量(replication offset)和从服务器的复制偏移量。

主服务器的复制积压缓冲区(replication backlog)。

服务器的运行ID ( run ID )。

4.1 复制偏移量

执行复制的双方——主服务器和从服务器会分别维护一个复制偏移量:
    主服务器每次向从服务器传播N个字节的数据时,就将自己的复制偏移量的值加上N
    从服务器每次收到主服务器传播来的N 个字节的数据时,就将自己的复制偏移量 的值加上N

通过对比主从服务器的复制偏移量,程序可以很容易地知道主从服务器是否处于一致状态


4.2 复制积压缓冲区

复制积压缓冲区是由主服务器维护的一个固定长度(fixed-size)先进先出(FIFO)队 列,默认大小为1MB。


当主服务器进行命令传播时,它不仅会将写命令发送给所有从服务器,还会将命令写入队到复制积压缓冲区里面

当从服务器重新连上主服务器时,从服务器会通过命令将自己的复制偏移量 offset发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行何种同步 操作:

部分重同步:
        如果offset偏移量之后的数据(也即是偏移量offset+1开始的数据)仍然存在 于复制积压缓冲区里面,那么主服务器将对从服务器执行部分重同步操作

完整重同步:
        如果offset偏移量之后的数据已经不存在于复制积压缓冲区,那么主服务 器将对从服务器执行完整重同步操作

缓冲区大小设置
        主服务器平均每秒产生的写命令数据量 (协议格式的写命令的长度总和)*2


4.3 服务器运行ID

除了复制偏移量和复制积压缓冲区之外,实现部分重同步还需要用到服务器运行ID (run ID ):

        每个Redis服务器,不论主服务器还是从服务,都会有自己的运行ID

        运行ID在服务器启动时自动生成,由40个随机的十六进制字符组成,例如53b9b 28df8042fdc9ab5e3fcbbbabffld5dce2b3

 

当从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID传送给从服务器, 而从服务器则会将这个运行ID保存起来。

当从服务器断线并重新连上一个主服务器时,从服务器将向当前连接的主服务器发送之 前保存的运行ID:

        如果从服务器保存的运行ID和当前连接的主服务器的运行ID相同,那么说明从服 务器断线之前复制的就是当前连接的这个主服务器,主服务器可以继续尝试执行部 分重同步操作

        如果从服务器保存的运行ID和当前连接的主服务器的运行ID并不相同, 那么说明从服务器断线之前复制的主服务器并不是当前连接的这个主服务器,主服 务器将对从服务器执行完整重同步操作

 

五、PSYNC命令的实现

 

六、复制的实现

6.1 设置主服务器的地址和端口

6.2 建立套接字连接

6.3 发送PING命令

6.4 身份验证

6.5 发送端口信息

6.6 同步

6.7 命令传播

 

七、心跳检测

在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令:

    REPLCONF ACK <replication_offset>

其中replication_of fset是从服务器当前的复制偏移量。

发送命令对于主从服务器有三个作用:

    1.检测主从服务器的网络连接状态。

    2.辅助实现min-slaves选项。

    3.检测命令丢失。

 

7.1 检测主从服务器的网络连接状态

主从服务器可以通过发送和接收命令来检查两者之间的网络连接是否 正常:如果主服务器超过一秒钟没有收到从服务器发来的命令,那么主服 务器就知道主从服务器之间的连接出现问题了。


7.2 辅助实现min-slaves配置选项

Redis 的 min-slaves-to-write 和 min-slaves-max-lag 两个选项可以防止主服 务器在不安全的情况下执行写命令。

min-slaves-to-write 3

min-slaves-max-lag 10

那么在从服务器的数量少于3个,或者三个从服务器的延迟(lag )值都大于或等于10 秒时,主服务器将拒绝执行写命令,这里的延迟值就是上面提到的命令的 lag 值。

 

7.3 检测命令丟失

    如果因为网络故障,主服务器传播给从服务器的写命令在半路丢失,那么当从服务器向 主服务器发送命令时,主服务器将发觉从服务器当前的复制偏移量少于自 己的复制偏移量,然后主服务器就会根据从服务器提交的复制偏移量,在复制积压缓冲区里 面找到从服务器缺少的数据,并将这些数据重新发送给从服务器。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值