在Redis中,用户可以通过执行SALVEOF命令,让一个服务器去复制另一个服务器。

127.0.0.1:12345> SLAVEOF 127.0.0.1 6379
OK
  • 6379的奴隶是12345。

旧版复制功能实现

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

  • 同步:将从服务器更新为主服务器的状态。
  • 命令传播:在主服务器状态被修改,导致主从状态不一致,让主从回到一致状态。

同步

客户端向服务器发送SYNC命令,SYNC步骤:

  1. 从 -> 主 发送SYNC。
  2. 主 执行BGSAVE命令,后台生成RDB,并且使用缓冲区记录 从 现在开始执行的所有写命令。
  3. RDB生成完毕时,发送给 从,从 载入这个RDB,更新至 主 执行BGSAVE时的数据库状态。
  4. 主 将缓冲区的写命令发给 从,从 更新至 主 当前的状态。

命令传播

在同步执行完毕之后,主从达到一致状态,但是当 主 执行客户端的命令时,主从再次不一致。

为了让主从再次回到一致状态,主 需要对 从 执行命令传播操作:主 会将自己执行的写命令发送给 从 ,这样就回

到主从一致了(迫真)。

旧版复制的缺陷

对于第一次复制来说旧版是可以的,但是对于断线后重连效率是很低的,因为,断线重连的服务器保存的数据大部

分是相同的,发送SYNC命令传送RDB文件并不是非做不可的!

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

新版复制功能的实现

为了解决旧版的问题,Redis从2.8开始,使用PSYNC代替SYNC。

PSYNC有完整重同步和部分重同步2个命令:

  • 完整重同步:与同步命令是一样的。

  • 部分重同步:如果条件允许,主 可以将主从服务器连接断开期间执行的写命令发送给 从。

部分重同步的实现

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

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

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

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

复制偏移量

A断线后,从服务器向主服务器发送PSYNC,报告A的offset为10086。

复制积压缓冲区

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

当主服务器进行命令传播时,不仅会将命令发送给从服务器,还会将写命令入队到缓冲区中。

因此,主服务器的缓冲区保存着最近传播的写命令,并且记录了每个字节的偏移量

当从服务器重新连上主服务器,从服务器发送自己的offset,主服务器根据这个offset决定执行何种操作:

  • 如果offset之后的数据仍然存在于缓冲区里,那么主服务器将对从服务器执行部分重同步。
  • 相反如果不存在于缓冲区里,那么执行完整重同步。

根据需要调整复制积压缓冲区大小

最小大小计算公式:second * write_size_per_second

second为从服务器重新连上主服务器的平均时间。

write_size_per_second是主服务器平均每秒产生的写命令数据量。

服务器运行ID

每个服务器运行后会自动生成40个随机十六进制字符的ID。

  1. 主 和 从 初次复制时,主 会将自己的ID给 从。

  2. 当从服务器断线并重新连上主服务器时,从服务器会发送之前保存的ID给 主,如果一致就可以部分重同步。

复制的实现

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

  2. 建立套接字连接

  3. 发送PING

  4. 身份验证

  5. 发送端口信息

  6. 同步

值得一提的是,在同步之前,只有 从 是 主 的客户端,同步之后,主 也是 从 的客户端。主从服务器双方都是对方

的客户端,他们才可以互相发送命令,主 才可以发送写命令改变 从 的数据库状态。

  1. 命令传播

Reference

《Redis设计与实现》

Redis新旧复制的更多相关文章

  1. redis 系列21 复制Replication (上)

    一.   概述 使用和配置主从复制非常简单,每次当 slave 和 master 之间的连接断开时, slave 会自动重连到 master 上,并且无论这期间 master 发生了什么, slave ...

  2. Redis持久化及复制

    一.持久化的两种方式 1.RDB: RDB是在指定时间间隔内生成数据集的时间点快照(point-in-time snapshot)持久化,它是记录一段时间内的操作,一段时间内操作超过多少次就持久化.默 ...

  3. Redis实现之复制(二)

    PSYNC命令的实现 在Redis实现之复制(一)这一章中,我们介绍了PSYNC命令和它的工作机制,但一直没有说明PSYNC命令的参数以及返回值.现在,我们了解了运行ID.复制偏移量.复制积压缓冲区以 ...

  4. ca33a_demo_c++_新旧代码的兼容char数组与vector_string相互转换

    /*ca33a_demo_c++33_CppPrimer_新旧代码的兼容_txwtech旧代码:数组和c风格字符串新代码:vector和string相互转换:c风格字符串<- ->stri ...

  5. Android新旧版本Notification

    Android新旧版本Notification 在notification.setLatestEventInfo() 过时了 以前: NotificationManager mn = (Notific ...

  6. Matlab神经网络函数newff()新旧用法差异

    摘要 在Matlab R2010a版中,如果要创建一个具有两个隐含层.且神经元数分别为5.3的前向BP网络,使用旧的语法可以这样写: net1 = newff(minmax(P), [5 3 1]); ...

  7. [ACM_数学] Taxi Fare [新旧出租车费差 水 分段函数]

    Description Last September, Hangzhou raised the taxi fares. The original flag-down fare in Hangzhou ...

  8. Flex布局新旧混合写法详解(兼容微信)

    原文链接:https://www.usblog.cc/blog/post/justzhl/Flex布局新旧混合写法详解(兼容微信) flex是个非常好用的属性,如果说有什么可以完全代替 float 和 ...

  9. 浅谈 angular新旧版本问题

    一直在学习angularJs,之前用的版本比较老,前些天更新了一下angularJs的版本,然后发现了一些问题,希望和大家分享一下. 在老的版本里控制器直接用函数定义就可以 比如: 在angularJ ...

随机推荐

  1. C++继承体系中的内存对齐

    本篇随笔讨论一个比较冷门的知识,继承结构中内存对齐的问题,如今内存越来越大也越来越便宜,大部分人都已经不再关注内存对齐的问题了.但是作为一个有追求的技术人员,实现功能永远都是最基本的要求,把代码优化到 ...

  2. java8 lambda表达式和函数式编程

    什么是函数式接口(Functional Interface) 其实之前在讲Lambda表达式的时候提到过,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法 (可以有def ...

  3. Kafka客户端内存缓冲GC处理机制--客户端内存

    1.Kafka的客户端缓冲机制 首先,先得给大家明确一个事情,那就是在客户端发送消息给kafka服务器的时候,一定是有一个内存缓冲机制的. 也就是说,消息会先写入一个内存缓冲中,然后多条消息组成了一个 ...

  4. 面试必问题:JS防抖与节流

    摘要:防抖与节流可谓是面试常见,其实很好理解,下面带你分分钟了解防抖与节流的基本思想与写法~ 本文分享自华为云社区<JS防抖与节流快速了解与应用>,作者:北极光之夜. . 一.速识防抖: ...

  5. promise小案例

    页面中有个板块,需要多张图片加载完之后才能进行显示 //页面中有个板块 需要多张图片加载完之后才能进行显示 const loadImg = (src) => { return new Promi ...

  6. vue系统总结2

    注册组件 组件其他补充 组件数据存放 父子组件通信 父级向子级传递信息 子级向父级传递信息 插槽slot 1.1什么是组件化 1.2 注册组件的基本步骤 创建组件构造器 注册组件 使用组件 <d ...

  7. javaScript知识储备

    javaScript知识储备 组成 ECMAScript(核心) 提供语法.变量等,遵循ECMA-262标准 DOM(文档对象模型) 提供操作HTML标签的API,遵循W3C规范 BOM(浏览器对象模 ...

  8. IS(上升子序列)

    前言:   这是一篇杂题选讲+作者口胡的博客,不喜勿喷. 正文:   提示:在阅读时请留意加粗的字体是"极长"还是"最长".   今天改题时碰到了一道关于线段树 ...

  9. Flask(6)- debug 模式

    使用 Flask 开发过程中存在两个常见的问题 当 Flask 程序出错时,没有提示错误的详细信息 修改 Flask 源代码后需要重启 Flask 程序 这两个问题非常的影响开发效率,因此 Flask ...

  10. 动态拼接表达式——Expression

    我们在项目中会遇到以下查询需求吗? 比如需要查询出满足以下条件的会员: 条件组一:30-40岁的男性会员 条件组二:20-30岁的女性会员 条件组三:60-80岁性别未知的会员 条件组内是并且关系,但 ...