当我们想要某个Redis服务器复制另一个服务器时,我们可以在连接这个Redis服务器的客户端上输入“SLAVEOF”命令指定另一个服务器的IP地址和端口号:
  SLAVEOF <master_ip> <master_port>。
  执行成功之后,这个服务器就成为指定服务器的从服务器,指定的服务器则是这个服务器的主服务器,从服务器会同步并复制主服务器的所有数据,与主服务器的数据库状态保持一致。本文要讲的就是2.8版本以后的Redis在客户端“SLAVEOF”命令输入回车以后都发生了什么。

1. 设置主服务器的地址和端口
  根据“SLAVEOF”命令中指定的IP地址和端口号,设置当前服务器(从服务器)状态中的主服务器地址属性“masterhost”和主服务器端口属性“masterport”:

  设置完成之后,便向客户端返回“OK”,而实际的复制工作则是在返回“OK”以后才开始执行的,即,“SLAVEOF”是一个异步命令。

2. 建立套接字连接
  从服务器根据“SLAVEOF”命令中指定的IP地址和端口号,创建连向主服务器的套接字连接。
  连接成功之后,从服务器将为这个套接字关联一个文件事件处理器,专门用于处理复制工作,比如,接收主服务器传送的RDB文件和写命令。
  而主服务器则为该套接字创建相应的客户端状态,并将从服务器当作一个连接到主服务器的客户端来对待。

3. 发送PING命令
  从服务器成为主服务器的客户端之后,做的第一件事就是向主服务器发送一个“PING”命令。作用有二:
(1)检查套接字的读写状态是否正常;
(2)检查主服务器能否正常处理命令请求。
  从服务器发送“PING”命令可能遇到的情况如下图所示:

4. 身份验证
  如果从服务器设置了“masterauth”选项,则需要向主服务器发送“AUTH”命令进行身份验证:
  AUTH <“masterauth”选项配置的值>。
  主服务器接收到“AUTH”命令发送的密码之后,将其与自身的“requirepass”选项设置的密码进行对比,来决定身份验证是否通过。
  整个流程如下图所示:

5. 发送端口信息
  从服务器向主服务器发送从服务器的监听端口号:
  REPLCONF listening-port <port_number>
  主服务器接收到以后将其记录在从服务器对应的客户端状态中:

  该属性目前唯一的作用:在主服务器执行“INFO replication”命令时打印出从服务器的端口号。

6. 数据同步
  Redis2.8版本以后的数据同步有两种方式:完整重同步和部分重同步。其中完整重同步与Redis2.8版本之前的方法一样,都是使用RDB文件;而部分重同步是Redis2.8版本之后引入的,为了实现部分重同步还需要引入复制偏移量和复制积压缓冲区两个概念:
(2)复制偏移量:执行复制的双方——主服务器和从服务器都会分别维护一个复制偏移量,可以通过对比双方的偏移量来确认是否处于一致状态。复制偏移量实质上是指当前服务器复制数据在复制积压缓冲区中的位置。
(1)复制积压缓冲区:这是主服务器维护的一个先进先出的队列,长度固定,默认为1MB,保存着主服务器最近执行的一部分写命令,并为队列中的每个字节记录相应的复制偏移量。
  所以,当主服务器进行命令传播时,它不仅会将写命令发送给所有从服务器,还会将写命令入列到复制积压缓冲区里面:

  开始数据同步时,从服务器根据自身情况向主服务器发送“PSYNC”命令:
(1)初次复制(以前没有复制过任何主服务器):PSYNC ? -1
(2)非初次复制(以前有复制过某个主服务器):PSYNC <runid> <offset>(“runid”为主服务器运行ID,“offset”为从服务器的复制偏移量)
  主服务器收到“PSYNC”命令之后,首先判断其中的“runid”是否与自身运行ID一致,若不一致则采取完整重同步操作;若一致则进一步判断“offset”,如果偏移量为“offset”之后的数据存在于复制积压缓冲区中则采取部分重同步操作,否则采取完整重同步操作。若决定采取完整重同步操作,主服务器将返回“+FULLRESYNC <runid> <offset>”,将自己的运行ID和当前复制偏移量发送给从服务器,从服务器则将主服务器的运行ID保存起来,用于下一次执行“PSYNC”命令时作为参数,同时将主服务器当前复制偏移量作为自己的初始化偏移量;若决定采取部分重同步操作,主服务器返回“+CONTINUE”,从服务器等待接收并执行主服务器发送的写命令即可。
  整个流程如下图所示:

  完整重同步和部分重同步的实现过程如下:
(1)完整重同步:
  主服务器执行“BGSAVE”命令,在后台生成一个RDB文件,同时使用一个缓冲区记录在开始生成RDB文件那一刻之后执行的所有写命令。
  主服务器将生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件来更新自己的数据库状态。
  主服务器将记录在缓冲区中的所有写命令也发送给从服务器,从服务器执行这些写命令之后,主从服务器的状态就一致了。
(2)部分重同步:
  主服务器根据从服务器的复制偏移量,在复制积压缓冲区中找到对应位置,将缓冲区中该位置之后的所有写命令数据都发送给从服务器,从服务器执行这些写命令之后,主从服务器的状态就一致了。

7. 命令传播
  主从服务器数据同步完成以后,主服务器只要一直将自己执行的写命令发送给从服务器,从服务器则一直接收并执行主服务器发送来的写命令,主从服务器就可以一直保持一致了。
  除此之外,从服务器还会默认以每秒一次的频率,向主服务器发送命令:
  REPLCONF ACK <replication_offset>(“replication_offset”为从服务器自身的复制偏移量)
  此命令是Redis2.8版本之后引入的,用于心跳检测,作用有三:
(1)检测主从服务器的网络连接状态
  “INFO replication”命令在列出的从服务器列表的“lag”一栏中记录了对应的从服务器最后一次向主服务器发送“REPLCONF ACK”命令距离现在过了多少秒,若超过1秒则说明主从服务器连接已经出现故障。
(2)辅助实现“min-slaves”配置选项
  “min-slaves-to-write”和“min-slaves-max-lag”两个选项的配置是为了防止主服务器在不安全的情况下执行写命令,例如:
  min-slaves-to-write 3
  min-slaves-max-lag 10
  那么在从服务器的数量少于3个,或者至少存在3个从服务器的延迟值都大于或等于10秒时,主服务器将拒绝执行写命令。这里的延迟值就是就是“INFO replication”命令中列出的从服务器列表的“lag”一栏中记录的值。
(3)检测命令丢失
  如果因为网络故障,主服务器传播给从服务器的写命令在半路丢失了。主服务器可以通过将自己的复制偏移量和从服务器在“REPLCONF ACK”命令中发送的偏移量进行比较来发现这一问题,然后在复制积压缓冲区中找到从服务器缺少的数据,并将这些数据重新发送给从服务器。

8. 断线重连
  当某个从服务器断线了,重新连上主服务器之后,从服务器需要重新发送“PSYNC”命令给主服务器,重新跑一遍第6步中的逻辑。其中主服务器需要根据从服务器的情况决定数据同步要采取完整重同步还是部分重同步,而完整重同步不论对于主服务器还是从服务器而言都是十分耗费资源的,所以我们当然希望断线重连的情况中尽可能多地进行部分重同步而不是完整重同步,这就需要合理设置主服务器的复制积压缓冲区的大小了。
  为了保证绝大部分断线重连情况都能使用部分重同步来处理,复制积压缓冲区的大小可以设置为:
  2 * 从服务器断线重连所需平均时间(秒) * 主服务器每秒产生的写命令数量

SLAVEOF以后的更多相关文章

  1. windows下Redis主从复制配置(报错:Invalid argument during startup: unknown conf file parameter : slaveof)

    主从复制配置中的遇到的异常: Invalid argument during startup: unknown conf file parameter :  slaveof 把Redis文件夹复制两份 ...

  2. Redis的 SLAVEOF 命令

    SLAVEOF host port SLAVEOF 命令用于在 Redis 运行时动态地修改复制(replication)功能的行为. 通过执行 SLAVEOF host port 命令,可以将当前服 ...

  3. windows环境redis主从安装部署

    准备工作 下载windows环境redis,我下载的是2.4.5,解压,拷贝一主(master)两从(slaveof).主机端口使用6379,两从的端口分别为6380和6381, 我本地索性用6379 ...

  4. 缓存、队列(Memcached、redis、RabbitMQ)

    本章内容: Memcached 简介.安装.使用 Python 操作 Memcached 天生支持集群 redis 简介.安装.使用.实例 Python 操作 Redis String.Hash.Li ...

  5. 深入浅出Redis-redis哨兵集群

    1.Sentinel 哨兵 Sentinel(哨兵)是Redis 的高可用性解决方案:由一个或多个Sentinel 实例 组成的Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所 ...

  6. [原]Redis主从复制各种环境下测试

    Redis 主从复制各种环境下测试 测试环境: Linux ubuntu 3.11.0-12-generic 2GB Mem 1 core of Intel(R) Core(TM) i5-3470 C ...

  7. Redis 简单搭建

    ======== redis ======== 1. redis setup and test : 1. download the package from https://redis.io/down ...

  8. Redis主从复制

    大家可以先看这篇文章ASP.NET Redis 开发对Redis有个初步的了解 Redis的主从复制功能非常强大,一个master可以拥有多个slave,而一个slave又可以拥有多个slave,如此 ...

  9. redis的安装配置

    主要讲下redis的安装配置,以及以服务的方式启动redis 1.下载最新版本的redis-3.0.7  到http://redis.io/download中下载最新版的redis-3.0.7 下载后 ...

随机推荐

  1. CPP-练习

    HW: 1.局部变量能否和全局变量重名? 答:能,局部会屏蔽全局.要用全局变量,需要使用"::" ;局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会 ...

  2. ios 团购信息客户端demo(三)

    接上二篇的内容,今天我们就来介绍一下如何将解析出来的数据放入AQGridView中显示出来,因为我们的工程中已经将AQGridView导入了,所以我们在KKFirstViewController中直接 ...

  3. 组合的输出(DFS)

    题目描述: 排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r<=n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数. 现要求你用递归的方法输出 ...

  4. 【Linux】用户与权限

    追加用户组 groupadd 用户组名 追加新用户 useradd -d 指定用户目录 -s 指定用户使用shell -g 指定用户组 -p 指定用户密码 用户名 更改用户  添加用户到其他组 use ...

  5. 使用python制作查询火车票工具

    使用python脚本实现查询火车票信息的效果图如下: 实现的代码: # coding: utf-8 """命令行火车票查看器 Usage: tickets [-gdtkz ...

  6. Python之写入文件(1)

    一.写入文件 保存数据也是在各个编程语言中常用的操作,将数据写入到文件中是常用的操作,你可以将程序运行中的一些临时输出保存至文件中,以便后续打开文件查看,也可以把这些文件读入程序中来操作其中的数据. ...

  7. teatime、

    Python之路,Day7 - 面向对象编程进阶   本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...

  8. Ajax四步操作

    第一步得到(XMLHttpRequest)function creatXMLHttpRequest(){ try{ return new XMLHttpRequest(); } catch(e){ t ...

  9. 【HIHOCODER 1529】 不上升序列

    描述 给定一个长度为 n 的非负整数序列 a[1..n]. 你每次可以花费 1 的代价给某个 a[i] 加1或者减1. 求最少需要多少代价能将这个序列变成一个不上升序列. 输入 第一行一个正整数 n. ...

  10. nw335 debian sid x86-64 -- 6 第三方驱动

    nw335 debian sid x86-64 -- 6 第三方驱动