工作需要,调研了一下redis的复制实现。在2.8版本之前和之后,复制方式有所不同。2.8之前的复制方式对于初次复制数据没有问题,对于断连接重新复制比较耗性能,因为都是全量复制。2.8之后对断线重连做了优化,采用差量复制。

旧版复制功能的实现

redis复制功能有同步命令传播两种。

同步操作将从服务器的数据库状态更新至主服务器当前的数据库状态;

命令传播用于在主服务器数据库状态改变,主从服务器数据状态不一致时,让主从服务器数据库状态重新回到一致状态。

同步

客户端向从服务器发送SLAVEOF命令,从服务器开始向主服务器请求同步数据,通过向主服务器发送SYNC命令完成同步过程,下面罗列SYNC命令的执行步骤:

1.从服务器向主服务器发送SYNC命令;

2.主服务器收到SYNC命令后执行BGSAVE命令,在后台生成一个rdb文件,并使用一个缓冲区记录从此刻开始执行的所有写操作命令;

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

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

下表展示一个主从同步的例子:
时间 主服务器 从服务器
t0 服务器启动 服务器启动
t1 执行SET K1 V1  
t2 执行SET K2 V2  
t3 执行SET K3 V3  
t4   向主服务器发送SYNC命令

t5

接收从服务器发来的SYNC命令,执行BGSAVE命令,创建包含K1,K2,K3的rdb文件,并用缓冲区记录接下来执行的所有写操作  
t6 执行SET K4 V4,并将这个命令保存到缓冲区  
t7 执行SET K5 K5,并将这个命令保存到缓冲区  
t8 BGSAVE命令执行完毕,向从服务器发送rdb文件  

t9

  接收并加载rdb文件,使数据库更新到主服务器执行BGSAVE命令时的数据库状态
t10 向从服务器发送缓冲区保存的写命令SET K4 V4和SET K5 V5  
t11   接收并执行主服务器发来的两个SET命令
t12 同步完成,现在注册服务器状态一致 同步完成,现在注册服务器状态一致

命令传播

同步操作完成之后,主从服务器数据库状态达到一致,后续的状态就靠命令传播保持主从服务器状态一致。主服务器会将自己执行的写操作命令,原封不动地发送给从服务器,从服务器执行相同的写操作之后,主从服务器数据库状态重新达到一致。

旧版本复制功能的缺陷

在redis2.8之前,从服务器对主服务器的复制分为以下两种情况:

1.初次复制:从服务器没有复制过任何主服务器,或者从服务器要复制的主服务器和上次复制的主服务器不同;

2.断线重连重新复制:处于命令传播的主从服务器因为网络原因而中断了复制,但从服务器通过自动重连重新连接上了主服务器,并重新从头开始全量复制主服务器。

对于初次复制而言,旧版复制功能可以较好的完成任务,但对于断线重连的情况,虽然可以让主从服务器重新回到一致,但是效率确是比较低下的。

SYNC操作是一个非常耗费资源的操作

每次执行SYNC命令时,主从服务器将执行以下动作:

1.主服务器执行BGSAVE生成rdb文件,此操作耗费主服务器大量的cpu,内存和磁盘io资源。

2.主服务器要将自己生成的rdb文件发送给从服务器,此操作会消耗主从服务器大量的网络资源,并对主服务器响应命令请求的时间产生影响。

3.接收到rdb文件的从服务器需要载入rdb文件,并且载入期间,从服务器因阻塞而无法处理命令请求。

新版复制功能的实现

为了解决旧版断线重连重复复制的低效问题,2.8版本开始使用PSYNC代替SYNC命令执行同步操作。PSYNC命令包括完整同步和部分同步:

1.完整同步用于处理初次复制的情况:PSYNC执行步骤和SYNC的执行步骤基本一样;

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

下表展示PSYNC命令解决断线重连的复制情况的例子:

时间 主服务器 从服务器
t1 主从服务器完成同步 主从服务器完成同步
t2 执行并传播SET K2 V2 执行主服务器传播来的SET K2 V2
t3 执行并传播SET K3 V3 执行主服务器传播来的SET K3 V3
   
t20 执行并传播SET K20 V20 执行并传播SET K20 V20
t21 主从服务器断开连接 主从服务器断开连接
t22 执行SET K22 V22 断线,尝试重连
t23 执行SET K23 V23 断线,尝试重连
t24 主从服务器重新建立连接 主从服务器重新建立连接
t25   向主服务器发生PSYNC命令
t26 向从服务器返回+CONTINUE回复,标识执行部分同步  
t27   接收主服务回复的+CONTINUE,准备部分同步
t28 向从服务器发送SET K22 V22和SET K23 V23两个命令  
t29   接收并执行主服务器传来的两个命令
t30 主从服务器再次完成同步,状态一致 主从服务器再次完成同步,状态一致

由此可见,PSYNC在执行部分同步的时候比执行SYNC命令所需要的资源少很多,速度也加快了。执行SYNC命令需要生成,传送,载入整个rdb文件,而PSYNC的部分同步只需将差量的写命令发送给从服务器便可。

部分重同步的实现

部分重同步由以下三部分组成:

1.主服务器的复制偏移量和从服务器的复制偏移量;

2.主服务器的复制积压缓冲区;

3.服务运行的id。

复制偏移量

执行复制的双方分别维护一个复制偏移量:

1.主服务器每次向从服务器传播N个字节的数据时,就将自己的复制偏移量加N;

2.从服务器每次收到主服务器传来的N个字节的数据时,就将自己的复制偏移量加N。

如果主从服务器数据库处于一致状态时,那么主从服务器的复制偏移量总是一致的,但是如果主从服务器偏移量不相同,说明主从服务器状态不一致。

复制积压缓冲区

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

当主服务器进行命令传播时,他会做两个操作,1.将命令发送给从服务器,2.将命令写入到复制积压缓冲区,因此复制积压缓冲区里会保存一部分最近传播的写命令,并且会为队列中的每个字节记录相应的复制偏移量,如下表所示。

偏移量 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095 10096
字节值 ‘*’ 3 ‘\r’ ‘\n’ ‘$’ 3 ‘\r’ ‘\n’ ‘S’ ‘E’ ‘T’

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

1.如果offset偏移量之后的数据仍然存在于复制积压缓冲区里面,那么主服务器会对从服务器进行部分同步操作;

2.如果offset偏移量之后的数据不在复制积压缓存区里面,那么主服务器对从服务器进行完整同步操作。

服务器运行id

每个redis服务器,无论主从服务,都会有自己的运行id。运行id在启动时生成,由40个随机的十六进制字符组成。

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

当从服务器断线并重连上上一个主服务器时,从服务器将保存的id发送给主服务器:

如果从服务器保存的运行id和当前连接的主服务运行id相同,说明从服务器断线之前复制的就是这台主服务器,主服务器可以继续吃、执行部分同步操作;

如果从服务器保存的运行id和当前连接的主服务器运行id不一致,那么说明从服务器断线之前连接的主服务器不是当前连接的主服务器民主服务器对从服务器执行完整同步操作。

总结

新redis的复制机制在老的复制机制上加了个部分同步,解决断线重连时的全量复制数据的低性能情况。部分同步的机制依赖于复制偏移量,复制积压缓冲区,服务运行id。

复制偏移量是为了让从服务器知晓下次该从何处开始进行部分重同步;

复制积压缓冲区是为了主服务器找到上次复制的点,从该点开始给从服务器复制数据。如果找不到这个点,就要执行完整同步过程了;

服务运行id主要是为保证重连的主服务器是否为上次连接的主服务器,如果是才能执行部分重同步,否则就只能进行完整同步了。

本文参考黄健宏著的 redis设计与实现

redis高可用 - 主从复制的更多相关文章

  1. redis高可用、redis集群、redis缓存优化

    今日内容概要 redis高可用 redis集群 redis缓存优化 内容详细 1.redis高可用 # 主从复制存在的问题: 1 主从复制,主节点发生故障,需要做故障转移,可以手动转移:让其中一个sl ...

  2. Redis高可用之主从复制实践(四)

    0.Redis目录结构 1)Redis介绍及部署在CentOS7上(一) 2)Redis指令与数据结构(二) 3)Redis客户端连接以及持久化数据(三) 4)Redis高可用之主从复制实践(四) 5 ...

  3. Redis高可用(持久化、主从复制、哨兵、集群)

    Redis高可用(持久化.主从复制.哨兵.集群) 目录 Redis高可用(持久化.主从复制.哨兵.集群) 一.Redis高可用 1. Redis高可用概述 2. Redis高可用策略 二.Redis持 ...

  4. Redis高可用之主从复制原理演进分析

    Redis高可用之主从复制原理演进分析 在很久之前写过一篇 Redis 主从复制原理的简略分析,基本是一个笔记类文章. 一.什么是主从复制 1.1 什么是主从复制 主从复制,从名字可以看出,至少需要 ...

  5. Redis 高可用集群

    Redis 高可用集群 Redis 的集群主从模型是一种高可用的集群架构.本章主要内容有:高可用集群的搭建,Jedis连接集群,新增集群节点,删除集群节点,其他配置补充说明. 高可用集群搭建 集群(c ...

  6. Redis高可用方案----Redis主从+Sentinel+Haproxy

    安装环境 这里使用三台服务器,每台服务器上开启一个redis-server和redis-sentinel服务,redis-server端口为6379,redis-sentinel的端口为26379. ...

  7. 9.Redis高可用-哨兵

    9.Redis高可用-哨兵9.1 基本概念9.1.1 主从复制的问题9.1.2 高可用9.1.3 Redis Sentinel的高可用性9.2 安装和部署9.2.1 部署拓扑结构9.2.2 部署Red ...

  8. Redis高可用详解:持久化技术及方案选择

    文章摘自:https://www.cnblogs.com/kismetv/p/9137897.html 前言 在上一篇文章中,介绍了Redis的内存模型,从这篇文章开始,将依次介绍Redis高可用相关 ...

  9. Redis高可用集群-哨兵模式(Redis-Sentinel)搭建配置教程【Windows环境】

    No cross,no crown . 不经历风雨,怎么见彩虹. Redis哨兵模式,用现在流行的话可以说就是一个"哨兵机器人",给"哨兵机器人"进行相应的配置 ...

随机推荐

  1. 基于标准库的string类实现简单的字符串替换

    感觉基本功还是不扎实,虽然能做些程序但是现在看来我还是个初学者(primer),试着完成习题结果还得修修改改. 废话不多说,实现功能很简单,<C++ Primer>9.5.2节习题. // ...

  2. 安装MySQL-python 的问题

    安装MySQL-python 的问题 1.CentOS下载mysql-devel安装 yum install mysql-devel 2.Ubuntu下不叫mysql-devel,而是叫libmysq ...

  3. 阻塞队列之五:LinkedBlockingQueue

    一.LinkedBlockingQueue简介 LinkedBlockingQueue是一个使用链表完成队列操作的阻塞队列.链表是单向链表,而不是双向链表.采用对于的next构成链表的方式来存储对象. ...

  4. Linux学习笔记 - Shell 输出命令

    1. echo 命令 echo 是基本的shell输出命令,她的语法是: echo string 我们也可以使用她来定制一些输出的格式,具体如下: 输出普通字符串 echo "it is a ...

  5. PHP中的traits简单理解

    Traits可以理解为一组能被不同的类都能调用到的方法集合,但Traits不是类!不能被实例化.先来例子看下语法: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 ...

  6. python写个Hack Scan

    前言: 之前逛SAFEING极客社区的时候 发现一款黑市卖2000多的软件,后面下载了 打不开.发现config文件里面有些不错的东西.总结了一下 有了以下的脚本. 脚本用处: [1]探测CMS(不敢 ...

  7. SVN更新或提交时出现冲突该如何解决

    解决版本冲突的命令.在冲突解决之后,需要使用svnresolved来告诉subversion冲突解决,这样才能提交更新.冲突发生时,subversion会在WorkCopy中保存所有的目标文件版本(上 ...

  8. Tkinter PanedWindow

         Tkinter PanedWindow: 一个PanedWindow是一个容器部件可能包含任何数量的窗格,水平或垂直排列 一个PanedWindow是一个容器部件可能包含任何数量的窗格,水平 ...

  9. springboot-shiro chapter02——springboot webmvc jsp

    简介:这一节主要涉及spring boot 支持jsp, 由于对spring boot不太熟悉,走了一些弯路. 环境:IDEA15+JDK1.8+Maven3+ 代码: https://git.osc ...

  10. sql server 2005 修改动态端口,连接字符串为:需要改成:IP地址+逗号+端口号才行

    1.sql server 2005 安装完毕后,默认是动态段,需要用sql brower 查询端口号:修改给固定端口后,格式为:IP地址+逗号+端口号. 2.sql 2000 的格式为:格式为:IP地 ...