主从复制

这是《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. AutoValue —— Generated immutable value classes

    本文参考 在<Effective Java>第三版第十条"Obey the general contract when overriding equals"中提到goo ...

  2. css预编译--sass进阶篇

    基础篇中主要介绍了一些sass的基本特性,进阶篇中,主要是写一些我们常用的sass控制命令,函数和规则. 控制命令 可能看过基础篇的朋友会发现在有些代码中出现@if @else @each等,熟悉JS ...

  3. 记离线缓存(manifest)一大坑,断定其只适用于静态网站或离线应用

    今天看了离线缓存(manifest)方面的资料,兴冲冲地就想给自己的网站用上.待我把代码都写好部署上服务器,并测试过OK的时候,在SegmentFault刷了一把manifest方面的问答,才发现这个 ...

  4. java中程序,进程和线程的区别

    2.程序,进程和线程的区别 马克-to-win:程序,进程和线程的区别是什么?这个问题比较抽象难理解,但又非常重要.我并不想给出一大堆抽象的学术解释,那样只能误国误民.所以我先给大家举一个例子.马克- ...

  5. Java中使用最频繁及最通用的Java工具类

    在Java中,工具类定义了一组公共方法,Java中使用最频繁及最通用的Java工具类. 一. org.apache.commons.io.IOUtils closeQuietly:关闭一个IO流.so ...

  6. IDEA小技巧:Debug条件断点

    今天给大家分享一个IDEA调试过程中的一个小技巧. 先来说说场景,你有没有碰到类似的情况,一个循环结构里,中间某一个情况可能会出错.比如下面的代码结果中,可能执行到第27次的时候,会出现问题. for ...

  7. Qt QComboBox之setEditable和currentTextChanged及其源码分析

    目录 Qt QComboBox之setEditable和currentTextChanged以及其源码分析 前言 问题的出现 问题分析 currentTextChanged信号触发 源码分析 Qt Q ...

  8. SpringMVC获取请求参数-POJO类型参数

    1.Controller中的业务方法的POJO参数的属性名与请求参数一致,参数值会自动映射匹配 1.创建POJO类 public class User { private String usernam ...

  9. Linux操作系统与项目部署

    Linux操作系统与项目部署 注意:本版块会涉及到操作系统相关知识. 现在,几乎所有智能设备都有一个自己的操作系统,比如我们的家用个人电脑,基本都是预装Windows操作系统,我们的手机也有Andro ...

  10. nmtui 工具使用的话,需要开启NetworkManager(网卡文件不存在ens192)

    环境采样: [root@k3master network-scripts]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) ...