Redis的主从复制

发布时间 2023-10-30 20:05:32作者: _mcj

1.主从复制的描述

  主从复制是指降Redis服务器的数据从其中一台,复制到另一台上去。其中提供数据的是主节点,接收数据的是从节点。数据的复制只能从主节点复制到从节点上。
  默认情况下每个启动的Redis服务都是主节点,可以通过修改配置,执行相关命令调整为从节点。另外一个主节点可以有多个从节点,但是一个从节点只能有一个主节点。

2.主从复制的作用

主从复制的作用,也可以说是主从复制的好处,主要有一下几点:

  • 读写分离,降压:能够是数据的读取和写入分开,主节点进行写数据,从节点进行读数据,降低Redis服务器的压力。
  • 数据备份,做后备:由于数据会从主节点复制到从节点中,那么当主节点出故障宕机之后,也可以切换到从节点继续工作,实现快速的故障恢复。
  • 高可用基石:主从复制是哨兵和集群能够实施的基础。

3.如何实现主从复制

3.1:建立复制
  这里需要注意一下,主从复制的开启只需要进行改从节点的配置即可,不需要懂主节点的配置。
从节点开启主从复制总共有三种方式,这三种方式是等效的:

  • 修改配置文件
    修改从节点配置文件中的:slaveof <masterip> <masterport>配置,其中<masterip>是主节点的id,<masterport>是主节点的端口。
  • 启动命令
    可以通过在启动命令后加入: --slaveof <masterip> <masterport>来开启主从复制,其中两个参数同第一种
  • 客户端命令
    在Redis服务启动之后,也可以在客户端执行命令:slaveof <masterip> <masterport>来开启,其中的两个参数也是同第一种。

3.2 样例

  • 启动两个redis实例
    在一台电脑上分别启动两个redis实例,其中一个端口为6379,一个端口为6380.
    6379端口的实例:
    image
    6380端口的实例:
    image
  • 创建从节点
    在6380端口的Redis实例执行:slaveof 127.0.0.1 6379命令将6380变为6379的从节点。
    image
    此时6380展示为:
    image
    可见它已经从主节点同步过来了130315bytes的数据,这是因为这里用的主节点本来就存在些数据的。
  • 结果验证
    (1)在从节点查询一个并不存在的数据。
    image
    (2)在主节点添加这个数据。
    image
    (3)在从节点再次查询这个数据,发现可以查询到了。
    image
    (4)在主节点删除该数据
    image
    (5)在从节点再次查询该key,可以发现又查询不到了
    image

ps:由于数据只能从主节点复制到从节点,因此从节点默认是不允许写数据的。如果需要写数据,可以通过设置slave-read-only属性为no来支持。
image

3.3 断开主从复制
如果创建了主从复制之后想要断开主从复制的话,可以通过slaveof no one命令来断开。断开后主从节点打印日志为:
主节点:
image
从节点:
image

4.主从复制的过程

主从复制的过程主要分为三个阶段:建立连接阶段,数据同步阶段,命令传播阶段。

  • 建立连接阶段
    该阶段主要是创建好主从节点之间的连接关系,为后面的数据同步做好准备。
    (1)保存主节点信息
    在从节点执行了slaveof命令之后,会在从节点内部保存下来主节点的ip和端口。可以看到从节点打印日志如下:
    image
    (2)建立socket连接
    从节点每秒1次调用复制定时函数replicationCron(),如果发现了有主节点可以连接,便会根据主节点的ip和port,创建socket连接。如果连接成功,则:
      从节点:为该socket建立一个处理器,负责后续的复制工作,如接收RDB文件、接收命令传播等。
      主节点:为socket创建相应的客户端状态,并将从节点看做是连接到主节点的一个客户端。
    该过程打印的日志为:
    image
    (3)发送ping命令
    发送ping命令进行请求,判断socket连接是否可用,以及主节点当前是否可以处理请求。
      如果主节点返回pong则说明一切正常,如果超时没有收到主节点的返回或者收到的返回不是pong,则断开连接,并重新连接。
    主节点返回pong时的日志打印:
    image
    (4)身份验证
    如果从节点设置了masterauth配置,则需要进行身份验证,该配置的值与必须与主节点设置的密码保持一致
    (5)发送从节点端口信息
    之后从节点将自己的端口号发送给主节点,主节点会将其存到该节点对应的客户端的slave_listening_port字段中。仅做一个显示作用
  • 数据同步阶段
    在主从节点之间的连接建立之后,就可以开始主从节点之间数据的同步。主要是为了保证主从节点数据的一致性。
      数据同步阶段可以根据主从节点当前状态的不同分为全量复制和部分复制。
    1:全量复制
    (1.1) 从节点向主节点发送全量复制的请求,或者从节点向主节点发送部分复制,但是主节点判断没法部分复制。
    (1.2) 主节点执行bgsave命令,生成RDB文件,并使用复制缓冲区记录从现在开始执行的所有写命令
    (1.3)主节点将RDB文件发送给从节点,从节点先清除自己的历史数据,然后载入接收的RDB文件,将数据库状态更新为主节点执行bgsave时的状态
    (1.4)主节点将复制缓冲区中的所有写命令发送给从节点,从节点执行命令,更新数据库的状态
    (1.5)如果从节点开启了AOF,则会触发bgrewriteaof的执行,从而保证文件更新得到主节点的最新状态
    从节点的执行日志如下,由于测试时从节点没有开启AOF所以加载后RDB就结束了:
    image
    2:部分复制
    部分复制有三个非常重要的部分,分别是复制偏移量(offset),复制积压缓冲区和服务器运行ID
    (2.1)复制偏移量(offset):主节点和从节点都会维护一个偏移量,用来表示主节点向从节点传递过来的字节数,主节点每次同步N个字节,就将offset加N。主要用来判断主从节点的数据库状态是否一致,offset相同则一致,不同则不一致
    (2.2)复制积压缓冲区:是由主节点维护的,固定长度的,先进先出队列,默认大小为1MB(可以通过repl-backlog-size配置来调整)。无论该主节点有多少个从节点,都只有一个复制积压缓冲区,用于备份主节点最近发送给从节点的数据。同时在后面的命令传播阶段,当主节点同步写命令给从节点时也会复制一份给复制积压缓冲区。
      当从节点再次复制时将offest发送给主节点时,主节点会根据offest判断之后的命令是否都在复制积压缓冲区中,如果都在则会进行部分复制,如果已经有数据不在复制积压缓冲区中,则进行全量复制。
    (2.3)服务器运行ID:主节点在初次复制时,会将自己的运行ID给从节点,从节点回保存该运行ID,当断线重连时会根据这个运行ID进行判断是全量复制还是部分复制,如果运行ID不同,则进行全量复制。运行ID相同,再看复制偏移量与复制积压缓冲区的情况,如果发送的offest之后的命令都在复制积压缓冲区中,那么则进行部分复制,否则也进行全量复制。
  • 命令传播阶段
    当数据同步阶段完成之后,主节点就进入命令传播阶段,这个阶段主节点会将自己执行的命令发送给从节点,同时复制一份到复制积压缓冲区,从节点接收到命令执行,来保证主从节点的数据一致性。由于命令传播时异步的过程,主从节点之间的网络状态,执行频率等的影响,因此主从节点之间复制会有延迟和不一致的情况。
      在命令传播阶段,由于要防止主从节点之间建立的连接断开了而不知道,因此主节点还维持了一个心跳机制:PING和REPLCONF ACK。
    PING
    PING是指每隔指定的时间(由repl-ping-slave-period配置控制,默认为10s),主节点会向从节点发送PING命令,主要是为了让从节点进行超时判断。
    REPLCONF ACK
    REPLCONF ACK是指从节点向主节点发送的命令,频率每秒一次,命令的格式为REPLCONF ACK {offset}, offset是指复制的偏移量。其作用是:
    • 实时监听主从节点网络状态,会被主节点用于复制超时的判断。
    • 监测命令丢失,从节点发送自身的offset,主节点会与自己的offset对比,如果从节点确实,主节点会推送缺失的数据给从节点(也会用到复制积压缓冲区)
    • 辅助保证从节点的数量和延迟

5.总结

  • 主从复制主的作用主要是用作读写分离,降压,故障恢复,做数据备份等功能。
  • 主从复制的开启主要是通过slaveof命令
  • 主从复制的过程可以分为三个阶段,创建链接,数据同步(有全量复制和部分复制),命令传播(维持了一个心跳机制:PING和REPLCONF ACK)