《Redis设计与实现》学习笔记-主从复制

为了提供整个缓存的可用性,可以给主服务器添加备用服务器,即从服务器。通过SLAVEOF命令把当前服务器设置成某台服务器的从服务器。

老版本同步过程

旧版本(2.8之前)主从服务器数据同步过程如下:

  1. 从服务器向主服务器发送SYNC命令。
  2. 主服务器接收到SYNC命令后调用BGSAVE命令生成一个RDB文件,在此过程中客户端对主服务器的修改命令存放在一个缓冲区中。
  3. 主服务器把生成的RDB文件发送给从服务器,从服务器通过加载该RDB文件更新数据库状态。
  4. 主服务器把缓冲区中的命令同步到从服务器,从服务器执行这些命令更新数据库。

老版本在SYNC命令同步处理有非常大的性能缺陷,在主从服务器断线重连之后执行同步动作时,也会生成完整的RDB文件并且发送到从服务器载入,但是主从服务器的数据库状态在断线前基本上是一致的,不一致的部分只有断线后主服务器执行那一部分修改数据库的命令,所以这时候SYNC命令就显得非常浪费,因为生成RDB文件时一个非常消耗CPU、内存和IO资源的过程,而发送RDB文件到从服务器也会占用大量的网络带宽资源,从服务器在载入RDB文件的过程中也阻塞不会相应任何命令,所以大部分情况下执行SYNC命令是没有必要也是非常不合理的。

为了解决2.8之前版本SYNC命令的性能问题,2.8版本设计了一个新的命令PSYNC,PSYNC命令分为完整重同步和部分重同步,完整重同步过程用于从服务器初始化时初次复制的情况和SYNC命令基本一致,PSYNC则用于断线后重新复制,在条件允许的情况下,它不会生成RDB文件,而是给从服务器回复一个+Continue表示执行部分重同步,并且把从服务器断线后主服务器执行的修改数据库的命令发送到从服务器,从服务器执行这些命令同步数据库。

部分重同步功能由下面几个部分构成:

  • 主服务器的复制偏移量和从服务器的复制偏移量:当主服务器在向从服务器进行命令同步时,主服务器和从服务器会各自记录一个复制偏移量,当主从服务器的数据库状态一致时这两个复制偏移量是相同的,如果这两个偏移量不一致说明当前主从服务器的状态不一致。
  • 主服务器的复制积压缓冲区:复制积压缓冲区是一个固定大小的FIFO队列,当队列已满时会弹出最早插入的数据,在主服务器进行命令传播时会同时把命令放到缓冲区中,缓冲区包含两部分数据,偏移量和字节。在进行复制时从服务器会将偏移量上报到主服务器,主服务检查当前偏移量是否还存在缓冲区中,如果存在进行部分重同步,如果不存在进行完整重同步。因为这个积压缓冲区是一个固定大小的队列,所以当从服务器长时间断线时,从服务器的复制偏移量很可能已不再缓冲区中,这时候只能进行完整重同步。
  • 服务器的运行ID:初次同步时主服务器会把ID发给从服务器,从服务器保存主服务器ID,当断线重连后,会把之前保存的主服务器ID上报给主服务器,主服务器检查从服务器之前复制的主服务器ID是否和自己的ID相同,如果相同,执行部分重同步,如果不同说明从服务器之前记录的状态不是当前主服务器,这时候需要执行完整重同步。

PSYNC命令实现

初始复制或者之前执行过SLAVEOF no one命令,执行完整重同步:发送PSYNC ? -1命令到主服务器。

如果从服务器已经复制过某个主服务器,在开始新复制时向主服务器发送PSYNC <runid> <offset>命令,runid是上次复制的主服务器id,offset是从服务器的复制偏移量,主服务器会根据这个两个参数来决定做哪种同步,判断服务器id是否和本机相同,复制偏移量是否在缓冲区中,主服务器有三种回复:

  • 回复+FULLRESYNC <runid> <offset>执行完整重同步,从服务器把offset当做初始复制偏移量
  • 回复+CONTINUE,表示执行部分重同步,从服务器等待主服务器发送缺少的数据
  • 回复-ERR,表示主服务器版本低于2.8,不支持PSYNC命令

新版本同步过程

2.8及以后版本复制过程:

  1. 设置主服务器地址和端口,通过调用SAVEOF <master_ip> <master_port>命令。
  2. 建立套接字连接。
  3. 发送PING命令,检查主从服务器是否能够正常处理命令。
  4. 身份验证,从服务器设置了masterauth并且主服务器设置了requirepass是需要进行身份验证。这两个选项要么都设置要么都不设置,如果只设置了一个从服务器向主服务器发送命令时会报错。
  5. 发送端口信息,通过执行命令REPLCONF listening-port <port-number>,向主服务器发送从服务器的监听端口号。
  6. 同步,从服务器向主服务器发送PSYNC命令。
  7. 命令传播,完成同步之后主服务器会把之后执行的写命令传播到从服务器保证主从服务器的状态一致。

心跳检测

在命令传播阶段,从服务器默认每秒一次的频率向主服务器发送命令:REPLCONF ACK <replication_offset>,replication_offset是从服务器的复制偏移量,该命令有三个作用:

  • 检测从服务器的网络连接状态,检测主从服务器连接是否正常,如果主服务器超过一定时间没有收到从服务器的REPLCONF ACK 命令,那么它们的连接可能出了问题。
  • 辅助实现min-slaves选项,min-slaves-to-write和min-slaves-max-lag两个选项可以防止主服务器在不安全的情况下执行写命令,min-slaves-to-write 3 min-slaves-max-lag 10 表示如果从服务器少于3个,或者3个从服务器的延迟都大于10秒时,主服务器拒绝写命令。
  • 检测命令丢失,主服务器接收到从服务器的REPLCONF ACK 命令之后会检查从服务器的偏移量是否和主服务器的一致,如果不一致会把积压缓冲区中的从服务器偏移量后面的命令发送到从服务器。
时间: 2024-10-13 07:01:17

《Redis设计与实现》学习笔记-主从复制的相关文章

Redis设计与实现读书笔记(一) SDS

作为redis最基础的底层数据结构之一,SDS提供了许多C风格字符串所不具备的功能,为之后redis内存管理提供了许多方便.它们分别是: 二进制安全 减少字符串长度获取时间复杂度 杜绝字符串溢出 减少内存分配次数 兼容部分C语言函数 下面将简要阐述SDS基础结构,并介绍这些功能相应的实现细节. SDS字符类型定义非常简单,以redis3.0.7为例: typedef char *sds; struct sdshdr { unsigned int len; //定义当前字符串长度(不包含'\0')

Redis 设计与实现读书笔记一 Redis字符串

1 Redis 是C语言实现的 2 C字符串是 /0 结束的字符数组 3 Redis具体的动态字符串实现 /* * 保存字符串对象的结构 */ struct sdshdr { // buf 中已占用空间的长度 int len; // buf 中剩余可用空间的长度 int free; // 数据空间 char buf[]; }; sdshdr free 0 len 5 buf ---> 'R' 'e' 'd' 'i' 's' '/0' 4 感觉更像 Java 中的 StringBuffer 的设计

linux内核设计与实现学习笔记-模块

模块 1.概念:  如果让LINUX Kernel单独运行在一个保护区域,那么LINUX Kernel就成为了“单内核”.    LINUX Kernel是组件模式的,所谓组件模式是指:LINUX Kernel在运行时,允许“代码”动态的插入或者移出Kernel.    所谓模块是指:相关的一些子程序,数据.入口点和出口点共同组合成的一个单一的二进制映像,也就是一个可装载的Kernel目标文件.    模块的支持,使得系统可以拥有一个最小的内核映像,并且通过模块的方式支持一些可选的特征和驱动程序

《响应式Web设计实践》学习笔记

原书: 响应式Web设计实践 第2章 流动布局 1. 布局选项 传统的固定布局中存在很多问题, 随着屏幕大小的越来越多元化, 固定布局已经不能适用了. 在流动布局中, 度量的单位不再是像素, 而是变成了百分比. 弹性布局与流动布局类似, 但是通常情况下, 弹性布局中会以em来作为单位. 带来一个好处是随着用户增大或减小字体, 适用弹性布局的元素的宽度也会等比例地变化. 但是其也可能出现水平滚动条 混合布局 媒体查询: 媒体查询允许根据设备的信息----诸如屏幕宽度, 方向或者分辨率等属性来使用不

Mariadb学习笔记-主从复制

Mariadb的主从复制 mysql的扩展模式:主从 读写分离基于MHA实现 主服务器配置 *修改配置文件 [[email protected] ~]# vim /etc/my.cnf.d/server.cnf [mysqld]server-id=1log-bin=master-loginnodb_file_per_table=ONskip_name_resolve=ON 启动mariadb服务 [[email protected] ~]# systemctl start mariadb [[e

设计心理学1学习笔记 - 日常的设计 - 第五章 认为差错?不,拙劣的设计

每当事故发生,我们分析事故,寻找原因,但当事故由人引起,我们便指责犯错误的人,而我们仍按照过去的方式做事情,如此的分析方式并不会从根本上改变这一切,我们应该用同样的方式对待所有的失败,找到根本原因,重新设计系统,保证不再发生同样的问题. 何以出错?出错的原因有很多,最常见的一种原因是要求人们在任务和流程中作为被自然规律的事情,譬如在数小时内保持警惕,或者在执行多个任务时保持精准的规范控制,最后,也许是最糟糕的归罪方式,是人们对待差错的态度,调查委员会无一例外地会发现犯错的人,重则解雇监禁,轻则反

JavaScript权威设计--CSS(简要学习笔记十六)

1.Document的一些特殊属性 document.lastModified document.URL document.title document.referrer document.domain document.write() document.writeIn() 2.查询选取的文本 使用鼠标mouseup事件 3.浏览器定义了多项文本编辑命令(富文本编辑器) 使用Document对象的execCommand()方法. document.queryCommandSupport()判断浏

Redis学习笔记~目录

redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set --有序集合)和hashs(哈希类型).这些数据类型都 支持push/pop.add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的.在此基础上,redis支持各种不同方式的排 序.与memcached一样,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更

Redis学习笔记4-Redis配置具体解释

在Redis中直接启动redis-server服务时, 採用的是默认的配置文件.採用redis-server   xxx.conf 这种方式能够依照指定的配置文件来执行Redis服务. 依照本Redis学习笔记中Redis的依照方式依照后,Redis的配置文件是/etc/redis/6379.conf.以下是Redis2.8.9的配置文件各项的中文解释. #daemonize no 默认情况下, redis 不是在后台运行的.假设须要在后台运行,把该项的值更改为 yes daemonize ye