前言

  关系数据库通常会使用一个主服务器向多个从服务器发送更新,并使用从服务器来处理所有的读请求,Redis采用了同样方法来实现自己的复制特性。

  简单总结起来就是:在接收到主服务器发送的数据初始副本之后,客户端每次主服务器进行写命令时,从服务器都会实时地得到更新。部署好主从服务器之后,客户端可以向任意的从服务器发送读请求。

  本文主要介绍Redis实现数据同步复制简单过程、新旧版本之间的对比、复制的实现、以及一些需要注意的细节,但不会涉及Redis源码解释。只对基本流程及功能进行详细描述。

  主要参考资料《Redis实战》与《Redis设计与实现》(有需要的同学可以私信或者评论)


一、旧版复制功能

  Redis 2.8以前采用的复制都为旧版复制,主要使用SYNC命令同步复制,SYNC存在很大的缺陷严重消耗主服务器的资源以及大量的网络连接资源。Redis 2.8之后采用PSYNC命令替代SYNC,解决完善这些缺陷,但在介绍新版复制功能之前,必须先介绍旧版复制过程,这样才能更好地形成对比。

  1、复制功能的两种模式

    同时复制过程分为同步sync与命令传播(command propagate),两个过程配合执行才能实现Redis复制。

    1)同步操作:

    通过从服务器发送到SYNC命令给主服务器-------->主服务器生成RDB文件并发送给从服务器,同时发送保存所有写命令给从服务器------>从服务器清空之前数据并执行解释RDB文件------->保持数据一致(还需要命令传播过程才能保持一致)

                  

         2)命令传播操作:

    主服务器的数据库状态被修改(主服务器执行写命令,修改数据库),导致主从服务器数据库不一致时,通过发送让主从服务器不一致的命令(主服务器接收到的新写命令)给从服务器并执行,让主从服务器的数据库重新回到一致状态。

    比如初次同步完成后,主从服务器数据库中都已经存在k1-k5的键,处于数据一致的状态

            

    之后,主服务器客户端发送DEL删除命令,删除k3键,导致主从服务器数据不一致

        

    为了让主从服务器数据再次回到一致状态,主服务器向从服务器发送DEL命令,紧接着从服务器接收并执行。即可回到一致状态

            

      

  2、配置选项前提

    1)主从复制的前提不用多说,就是先正确配置redis主从服务器,主要通过slaveof ip port选项配置或者SLAVEOF 命令。

    2)保证主服务器的RDB+AOF配置正确,特别是RDB中dbfilename选项与AOF中的dir选项,两个文件路径对于Redis是可写的

  3、主从复制过程

              

    文字简单总结描述:

    1)slave会建立和master的连接,然后发送sync命令;

    2)master都会启动一个后台进程执行BGSAVE命令,将数据快快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来;、

    3)后台进程完成写文件后,master发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。\

    4)紧接着master就会把缓存命令转发给slave,后续的master收到的写命令也通过跟slave连接发送给slave;

    5)如果master同时接收到多个slave发来的同步连接请求,只会启动一个进程来写数据库镜像,然后发送给所有slave。

    也可以参考以下表,其中步骤1-4可以认为是sync同步操作,而步骤5即为命令传播模式  

    

       

  注意事项

    1)从服务器在同步时,会清空所有数据,服务器在与主服务器进行初连接时,数据库中的所有数据都将丢失,替换成主服务器发送的数据。

    2)Redis不支持主主复制

    3)主从复制不会阻塞master(不会阻塞master处理客户端请求),相反slave在初次同步数据时会阻塞不能处理客户端请求。

    4)当多个从服务器尝试连接同一个主服务器的时候,就会出现以下两种情况:

  一是:步骤3还未执行,所有从服务器都会接收到相同的快照文件和相同缓冲区写命令。

  二是:步骤3正在执行或者已经执行完毕,当主服务器与较早的从服务器完成以上全部步骤之后,主服务器会新连接的从服务器重新依次执行1-5步骤。

 在大部分情况下,Redis会尽可能去减少复制所需要的工作,但是从服务器连接的时机不凑巧的话,只好多做一些外额外工作。

    5)多个从服务器连接主服务器时候,同步数据可能会占用很大一部分的带宽,可能会导致其他请求难以到达主服务器。

  4、SYNC命令的缺陷

    主要是主从服务器断线后重复制,即处于命令传播阶段的主从服务器由于网络断开,从服务器一直尝试连接主服务器连接成功后,继续复制主服务器。如下过程在主从服务器断开后重新连接期间,主服务器继续执行三个SET命令,导致从服务器连接后发送L SYNC命令,重新进行了“全量”复制过程,RDB文件中包含k1-k10089全部的键。

         

   其中可以明显看出重新连接主服务器之后,SYNC命令创建包含k1-k10089的RDB文件。而事实上只需要再同步断线后的k10087-k10089即可。SYNC的“全同步”对于从服务来说是不必要的。

SYNC命令非常消耗资源,原因有三点:

    1)主服务器执行BGSAVE命令生成RDB文件,这个生成过程会大量消耗主服务器资源(CPU、内存和磁盘I/O资源)

    2)主服务器需要将自己生成的RBD文件发送给从从服务器,这个发送操作会消耗主从服务器大量的网络资源(带宽与流量)

    3)接收到RDB文件你的从服务器需要载入RDB文件,载入期间从服务器会因为阻塞而导致没办法处理命令请求。

   

二、新版复制功能

  为了解决旧版本中断线情况下SYNC低效问题,在Redis 2.8之后使用PSYNC命令代替SYNC命令执行复制同步操作,自然PSYNC具备完整重同步和部分重同步模式

    1)完整重同步:跟旧版复制基本是一致的,可以理解为“全量”复制。

       2)部分重同步:在命令传播阶段,断线重复制只需要发送主服务器在断开期间执行的写命给从服务器即可,可以理解为“增量”复制。

  断开连接后发送+CONTINUE回复,表示使用PSYNC部分重同步,只需要同步k10087-10089即可,不需要生成RDB文件

        

  相关流程图如下:

          

三、复制的实现

  Redis不管是旧版还是新版,复制的实现都可以分为七个步骤,流程图如下:

          

1、设置主服务的地址与端口

当客户端向从服务器发送一下命令时或者在配置文件中配置slaveof选项

  1. 127.0.0.1:12345> SLAVEOF 127.0.0.1 6379

从服务器将向发送SLAVEOF命令的客户端返回OK,表示复制指令已经被接收,而实际上复制工作是在OK返回之后进行。

2、建立套接字连接

从服务器根据设置的套接字创建连向主服务器的套接字连接

主服务器接收从服务器的套接字连接之后,为该套接字创建响应的客户端状态,并将此时的从服务器看做是主服务器的客户端,也就是该从服务器同时具备服务器与客户端两个身份。

3、发送PING命令

从服务器成为主服务器的客户端之后,做的第一件事就是向主服务器发送PING命令。PING命令主要有两种作用:

  1) 虽然建立了套接字连接,但是还未使用过,通过发送PING命令检查套接字的读写状态是否正常

  2) 通过发送PING命令检查主服务器能否正常处理命令请求

  从服务器在发送PING命令之后将遇到以下三种情况的其中一种:

  1) 主服务器向从服务器返回一个回复,但是从服务器却不能在规定的会时间(timeout)内读取命令回复的内容,则表示当前主从服务器之间的网络状态连接不佳,不能基础执行复制工作的后续步骤,这时从服务器会断开套接字连接重新创建。

  2) 主服务器向从服务器返回一个错误,那么表示主服务器暂时没有办法处理从服务器的命令请求,不能继续执行复制工作的后续步骤,这时从服务器会断开套接字连接重新创建。

  3) 如果从服务器读取到“PONG”回复,那么表示主从服务器之间网络连接正常,并且主服务器可以处理从服务器发送的命令请求。

 

             

  

4、身份验证

从服务器接收到主服务器返回的“PONG”回复,接下来就需要考虑身份验证的事。

如果从服务器设置了masterauth选项,那么进行身份验证

如果从服务器没有设置masterauth选项,那么不进行身份验证

  从服务器在身份验证的时候可能遇到三种情况

  1) 主服务没有设置requirepass选项,并且从服务器也没有设置masterquth选项,那么主服务器继续执行从服务器命令,完成复制工作

  2) 如果从服务器通过AUTH命令发送的密码与主服务器中requirepass密码相同,那么主服务器将继续执行从服务器发送的命令,复制工作继续,与此相反,密码不一致,则会返回invalid password错误

  3) 如果从服务器没有设置masterauth选项,而主服务器设置了requirepass选项,那么主服务器将返回一个NOAUTH错误。反之没有设设置masterauth选项,而设置了requirepass选项,那么会返回no password is set错误。

                

5、发送端口信息

         在身份验证步骤之后,从服务器将执行命令REPLCONF listening-port <port>,向主服务器发送从服务器的监听端口号。

  

6、同步

就是上述所指的同步操作,从服务器向主服务器发送PSYNC命令,执行同步操作,值得注意的是只有从服务器是主服务器的客户端,但是执行同步操作之后,主服务器也会成为从服务器的客户端。

7、命令传播

 主从服务器就会进入命令传播阶段,主服务器只要将自己执行的写命令发送给从服务器,而从服务器只要一直执行并接收主服务器发来的写命令(上述已经介绍过,这里不过多介绍)

Redis的复制是如何实现的?的更多相关文章

  1. 14、Redis的复制

    写在前面的话:读书破万卷,编码如有神 --------------------------------------------------------------------------------- ...

  2. Redis的复制特性

    对于有扩展平台以适应更高负载经验的工程师和管理员来说,复制(replication)是不可或缺的.复制可以让其他服务器拥有一个不断更新的数据副本,从而使得拥有数据副本的服务器可以用于处理客户端发送的读 ...

  3. Redis 之复制-初入江湖

    一.前言 在分布式系统中,为了解决单点问题,通常会把数据复制多个副本部署到其他机器,满足故障恢复合负载均衡等需求.Redis也是如此,它为我们提供了复制的功能,实现了相同数据的多个Redis副本.复制 ...

  4. Redis(八):Redis的复制(Master/Slave)

    Redis的复制(Master/Slave)目录导航: 是什么 能干嘛 怎么玩 复制原理 哨兵模式(sentinel) 复制的缺点 是什么 官网 行话:也就是我们所说的主从复制,主机数据更新后根据配置 ...

  5. Redis的复制(Master/Slave)、主从复制、读写分离

    1.什么是Redis的复制 行话:也就是我们所说的主从复制,主数据更新后根据配置和策略自动同步到备用机的master/slave机制,Mater以写为主,slave以读为主. 2.能干什么 2.1.读 ...

  6. 8.Redis的复制(Master/Slave)

    Redis的复制(Master/Slave) a)是什么 行话:也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave ...

  7. Redis系列(四):Redis的复制机制(主从复制)

    本篇博客是Redis系列的第4篇,主要讲解下Redis的主从复制机制. 本系列的前3篇可以点击以下链接查看: Redis系列(一):Redis简介及环境安装 Redis系列(二):Redis的5种数据 ...

  8. Redis之复制

    1.配置 1.1 建立复制 参与复制的Redis实例划分为主节点(master) 和从节点(slave).默认情况下,Redis都是主节点.每个从节点只能有一个主节点,而主节点可以同时具有多个从节点. ...

  9. Redis的复制(Master/Slave)

    是什么 : 也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主 能干嘛: 读写分离,容灾恢复 怎么玩: 1 ...

  10. Python Redis 数据复制.

    1 > 下载Python操作Redis的客户端 https://pypi.python.org/pypi/redis/2.7.6 下载完成后,参考该网站相关命令,执行安装. 2 > 下载 ...

随机推荐

  1. Kubernetes1.7—DNS安装

    虽然通过了Service解决了Pod重建后IP动态变化(服务发现).负载均衡问题,但使用Service还是要需要知道CLUSTER-IP,而通过NDS可以解决该问题:在Kubernetes集群中可通过 ...

  2. angular.module()

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. java.lang.ClassCastException: net.sf.json.JSONNull cannot be cast to net.sf.json.JSONObject的解决方法

    报错情况已经说明了,在百度查了好几个解决方法,这里总结一下: 首先:加一个判断是否为空,再做操作 // 得到json串 String jsonString = UtilPOSTGET.UPost(FO ...

  4. java的3大特性

    java的3大特性 1.继承: * 继承是从已有类得到继承信息创建新类的过程. * 提供继承信息的类被称为父类(超类.基类):得到继承信息的类被称为子类(派生类). * 继承让变化中的软件系统有定的延 ...

  5. 文件访问时间简记(Modify time 和 Change time)

    [root@77-29-68-bx-core]# stat hql.out File: 'hql.out' Size: 13750 Blocks: 32 IO Block: 4096 regular ...

  6. 小程序----选择地理位置 ( wx.chooseLocation ) 和 获取地理位置 (wx.getSetting)

    问题来了:假如我第一次使用wx.chooseLocation()获取权限被拒绝,然后使用wx.getSetting()来重新获取权限该怎么做呢? 思路:wx.chooseLocation()有fail ...

  7. 干货分享: 长达150页的openvswitch的ppt,不实验无真相

    下载链接: Openvswitch实验教程 http://files.cnblogs.com/popsuper1982/Openvswtich.pptx 一.概论 Software Defined N ...

  8. CSS3禁止用户选中文字——user-select: none;

    需求:现在有一个需求是在移动端让你禁止用户选中文字,你会怎么做呢?如下图    解决方法:使用CSS3新增属性 user-select: none;   -webkit-user-select:non ...

  9. [Swift]LeetCode241. 为运算表达式设计优先级 | Different Ways to Add Parentheses

    Given a string of numbers and operators, return all possible results from computing all the differen ...

  10. [Swift]LeetCode859. 亲密字符串 | Buddy Strings

    Given two strings A and B of lowercase letters, return true if and only if we can swap two letters i ...