主从复制

这是《Redis设计与实现》系列的文章,系列导航:Redis设计与实现笔记

SLAVEOF

新旧复制功能

旧版复制功能

旧版复制功能的实现为 同步命令传播

当刚连上Master时,要做一次全同步:

sequenceDiagram
participant Slave
participant Master
Slave->>Master: SYNC
Master->>Master: BGSAVE
Master->>Master: 记录此时的命令到缓冲区中
Master->>Slave: 发送RDB
Master->>Slave: 发送命令缓冲区中的命令

之所以要用到缓冲区是因为,在主节点进行 BGSAVE 的过程中如果有命令执行,那么我们要把这些命令也记录下来。

之后,主从节点之间只用 命令传播 就可以做到同步了,也就是说主节点执行什么命令,从节点跟着执行。(当然,一些随机、时间类的函数会直接转换成定值)

旧版复制的缺陷

如果从节点断线后重新连接,旧版复制功能的效率很低,因为为了让从服务器补足一小部分的确实却要进行一次 SYNC 命令

为什么低效:

  1. 主节点 BGSAVE 要消耗大量的CPU、内存、IO资源
  2. 主节点发送需要消耗网络资源
  3. 从节点需要载入,且载入期间处于阻塞状态

新版复制功能

PSYNC 命令代替 SYNC。

PSYNC 具有 完整重同步部分重同步 两种模式,分别针对初次同步和重新同步两种场景。

复制功能的实现

复制的实现

复制的一些具体的细节,当进行复制时:

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

    struct redisServer{
    //...
    char *masterhost;
    int masterport;
    //...
    }
  2. 建立套接字连接,并关联一个专门处理复制工作的文件事件处理器

  3. 发送 PING 命令,检查套接字和主服务器的状态是否正常

  4. 身份验证,主从必须配置一致且密码正确(如果有)才能通过验证

  5. 发送端口信息:主节点也得知道给从节点的哪个端口发消息,不是么

  6. 同步:干正事儿喽

    这里书上说:

    • 在同步操作执行之前,只有从服务器是主服务器的客户端,但是在执行同步操作之后,主服务器也会成为从服务器的客户端。
    • 正是因为主服务成为了从服务器的客户端,所以主服务器才能通过发送写命令来改变从服务器的数据库状态。

    我想了想,似乎一般确实都是客户端改变服务端的数据的,所以这么说倒也在理,但是服务端不是也可以给客户端发送数据么?所以这里可能和 Redis 的具体实现有关?

  7. 命令传播:进入了第二个阶段

如何部分重同步

要关注的三个部分:

  1. 复制偏移量:主从服务器都有复制偏移量,通过这个值判断主从是否处于一致状态

  2. 主服务器的复制积压缓冲区:保存执行命令的历史记录

    一个固定长度(默认1MB)的 FIFO 的队列,当主从不一致时可以计算并从中获取缺少的命令。

    由于固定长度,所以如果缺的多了就只能进行完整重同步了。

    大小一般设为 断连平均时间 * 每秒的命令数,安全起见再乘以2。

  3. 服务器的运行 ID

    毕竟只有 ID 一致同步才有意义,否则说明换主人了,那还是全同步吧

PSYNC的逻辑

graph LR;

S(接收到SLAVEOF命令) --> A{第一次复制?}
A --Y--> A1[发送PSYNC ? -1] --> E1(返回+FULLRESYNC &ltrunid> &ltoffset&gt)
A --N--> A2[发送PSYNC &ltrunid&gt &ltoffset&gt] --> B{主服务器返回 +CONTINUE}

B --N--> E1
B --Y--> E2[执行部分重同步]

主要是判断 是否是第一次复制是否是同一个主服务器,从而决定是部分重同步还是全同步。

上图没有展示的是,如果主服务器不支持 PSYNC,则返回 -ERR

心跳检测

心跳检测:在命令传播阶段,从服务器默认每秒发送一次心跳:REPLCONF ACK <replication_offset>

作用有三:

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

  2. 辅助实现 min-slaves 配置选项

    min-slaves-to-write、min-slaves-max-lag 可以防止发生脑裂现象

  3. 通过 offset 检测命令是否丢失

Redis设计与实现3.1:主从复制的更多相关文章

  1. 探索Redis设计与实现12:浅析Redis主从复制

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  2. Redis如何实现高可用【主从复制+哨兵机制+keepalived】

    实现redis高可用机制的一些方法: 保证redis高可用机制需要redis主从复制.redis持久化机制.哨兵机制.keepalived等的支持. 主从复制的作用:数据备份.读写分离.分布式集群.实 ...

  3. 探索Redis设计与实现15:Redis分布式锁进化史

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  4. 探索Redis设计与实现14:Redis事务浅析与ACID特性介绍

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  5. 探索Redis设计与实现13:Redis集群机制及一个Redis架构演进实例

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  6. 探索Redis设计与实现11:使用快照和AOF将Redis数据持久化到硬盘中

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  7. 探索Redis设计与实现10:Redis的事件驱动模型与命令执行过程

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  8. 探索Redis设计与实现9:数据库redisDb与键过期删除策略

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  9. 探索Redis设计与实现8:连接底层与表面的数据结构robj

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

随机推荐

  1. springboot项目如何添加热部署

    环境jdk1.8.maven3.6.使用工具为idea 1.在pom.xml文件中添加依赖 <dependency> <groupId>org.springframework. ...

  2. Docker最常用的镜像命令和容器命令

    一.镜像相关命令 官方文档:https://docs.docker.com/referenc 1.1查看镜像 [root@localhost ~]# docker images REPOSITORY ...

  3. 基于MPC算法的车辆多目标自适应巡航控制系统研究_荆亚杰

  4. java中如何求出2008年的第1星期星期一是几号?

    题目8: 2008年的第1星期星期一是几号? import java.util.*; public class Test {     public static void main(String[] ...

  5. XShell免费版的安装配置教程以及使用教程(超级详细)

    ​一. XShell的作用 XShell可以在Windows界面下来访问远端不同系统下的服务器,从而比较好的达到远程控制终端的目的.它支持 RLOGIN.SFTP.SERIAL.TELNET.SSH2 ...

  6. LC-26

    class Solution { public int removeDuplicates(int[] nums) { int slowIndex = 0, fastIndex = 1; if (num ...

  7. Java基础语法01——变量与运算符

    本文是对Java基础语法的第一部分的学习,包括注释:标识符的命名规则与规范:变量的数据类型分类以及转换:以及六种运算符(算术.赋值.比较.逻辑.三元和位运算符).

  8. Bootstarp框架用法

    Bootstrap框架 Bootstrap框架 2.X 3.X 4.X # 推荐使用3.X版本 使用框架调整页面样式一般都是操作标签的class属性即可 bootstrap需要依赖于jQuery才能正 ...

  9. eclipse项目导入工作空间提示已存在问题

    项目直接放在 workspace 目录下,必须项目名和项目文件夹名相同,主要找的是eclipse 项目文件夹下的 .project 文件中的 <name> ... </name> ...

  10. 基于 Apache Hudi 构建增量和无限回放事件流的 OLAP 平台

    1. 摘要 在本博客中,我们将讨论在构建流数据平台时如何利用 Hudi 的两个最令人难以置信的能力. 增量消费--每 30 分钟处理一次数据,并在我们的组织内构建每小时级别的OLAP平台 事件流的无限 ...