Redis一主多从复制

/ Redis / 2 条评论 / 739浏览

在上一篇中,我们简单的介绍了Redis的复制的功能,并且已经通过相关的例子演示了,Redis复制功能的具体使用。在这一篇中我们主要介绍一下Redis一主多从复制,因为上一篇中我们主要演示的是一主一从,除此之外,在一篇中我们还将介绍Redis复制功的原理等内容。


在介绍一主多从复制之前,我们先思考一下问题,就是主从复制会将主节点的数据全部复制到从节点,但这样有一个问题,就是如果其它用户可以访问从节点的数据,那么就相当于间接的获取·了主节点的数据了,在数据安全性方面考虑,这显示是不安全的。Redis为了解决这样的问题,主节点通常会设置requirepass参数进行密码验证,这样当我们访问从节点时,必须使用auth命令进行校验,从而保证Redis中的数据安全。除此之外,当Redis为从节点是,会自动设置该节点为只读模式。当节点为指定模式时,禁止执行修改操作。那为什么Redis要设置从节点为只读模式呢?这是因为如果从节点可以执行修改操作,那么势必会导致主从节点数据不一致的可能,所以Redis为了保证数据的一致性,禁止从节点执行修改操作。


一主一从也就是上一篇中介绍的那样,一个主节点下只有一个多节点,这种方式常常用于当主节点发生故障时采用用从节点继续提供服务。如果Redis并发写操作比较多时并且需要持久化时,我们可以在从节点上开启AOF,这样可既可以保证数据的持久化,还可以必免持久化对主节点的性能干扰。


顾名思义一主多从就是一个主节点下面有多个从节点。这种方式通常会做Redis读写分离业务。这样可以分担主节点的压力。除此之外,我们还可以通过一主多从将比较耗时的命令放到任意的从节点中,这样可以有效的防止慢查询对主节点造成阻塞,从而影响Redis服务的稳定性。


这种方式可以使得从节点不但可以复制主节点数据,同时还可以作业其它从节点的主节点继续向下复制,类似树状结果,所以叫做树状主从。这种方式可以有效的降低主节点的负载。


下图为以上3种结构的结果图:

img


Redis在复制时底层采用的是psync命令完成的数据主从同步,同步主要分为:全量复制和部分复制两种。

在底层使用psync命令运行时需要以下几个条件:


从节点使用psync命令完成部分复制和全量复制功能,命令格式:psync{runId}{offset}。参数说明如下:

具体操作如下:

  1. 从节点发送psync命令给主节点,参数runId是当前从节点保存的主节点运行ID。offset参数是当前从节点保存的复制偏移量,如果是第一次复制,则默认值为-1。
  2. 主节点根据psync参数和自身数据情况决定响应结果:

全量复制是Redis最早支持的复制方式,触发全量复制的命令是sync和psync。下面我们介绍一下Redis中全量复制的流程:

  1. 发送psync命令进行数据同步,由于是第一次进行复制,从节点没有复制偏移量和主节点运行ID,所以发送psync ?-1。
  2. 主节点根据psync ? -1解析出不前为全量复制,回复+FULLRESYNC相应。
  3. 从节点接受主节点的相应数据保存运行ID和偏移量offset。
  4. 主节点执行bgsave保存RDB文件到本地。
  5. 主节点发送RDB文件给从节点,从节点把接受的RDB文件保存在本地并直接作为从节点的数据文件,接受完RDB文件后从节点打印相关日志。
  6. 从节点开始接受RDB文件到接受完成期间,主节点仍然响应读写命令,因此主节点会把这期间写命令保存在客户端的缓冲区中,当从节点加载完RDB文件后,主节点在把缓冲区的数据发送给从节点,已保证主从之间的数据一致性。如果主节点和从节点RDB文件的数据传输时间过长时,按上面分析可能会造成客户端的缓冲区溢出。默认配置为client-output-buffer-limit slave 256MB 64MB 60。如果60秒内缓冲区消耗大于64MB或者超过256MB时,主节点将直接关闭客户端连接,造成全量同步失败。
  7. 从节点接受完主节点传送来的全部数据后会清空自身的旧数据。
  8. 从节点清空数据后开始加载RDB文件,如果RDB文件比较大时,该操作也是比较耗时的。
  9. 从节点成功加载完RDB文件后,如果当前节点开启了AOF持久化功能,它会立刻做bgrewriteaof操作,为了保证全量复制后AOF持久化文件立刻可用。

上述内容就是Redis全量复制的相关流程,并且通过上述流程的介绍,我们知道Redis全量复制是非常耗时的。它的开销主要包括下面几个流程:

正向上面所说的Redis全量复制是比较耗时的,如果RDB文件非常大时,全量复制的总耗时会更长,并且这期间会大量消耗主从节点所在服务器的CPU、内存和网络资源。所以除了第一应该使用全量复制外,其它场景应该尽量必免使用全量复制。由于Redis全量复制有种种弊端,由是Redis提供了部分复制功能,下面我介绍一下Redis中的部分复制功能。


部分复制主要是Redis针对全量复制的过高开销做出的一种优化措施,使用psync{runId}{offset}命令实现。当从节点正在复制主节点时,如果出现网络中断或者命令丢失时,从节点会向主节点要求补发丢失的命令数据。因为补发的数据一般来说都会小于全量的数据,所以开销很小。下面我们介绍一下Redis中部分复制的流程:

  1. 当主从节点之间网络出现中断时,如果超过repl-timeout时间,主节点会认为从节点故障并中断复制连接。
  2. 主从连接中断期间主节点依然可以响应命令,但因复制连接中断命令无法发送给从节点,但主节点内部会将这段时间的命令保存在客户端缓冲区中,默认大小为1MB。
  3. 当主从节点网络恢复后,从节点会再次连接上主节点。
  4. 当主从节点连接恢复后,由于从节点之前保存了自身的偏移量和主节点的运行ID。因此会把它们当作psync参数发送给主节点,要求进行部分复制操作。
  5. 主节点接到psync命令后首先核对参数runId是否与自身一致,如果一致,说明之前复制的是当前主节点,之后根据参数offset在自身的缓冲区中查找,如果偏移量之后的数据存在缓冲区,则对从节点发送+CONTINUE相应,表示可以进行部分复制。
  6. 主节点根据偏移量把缓冲区里的数据发送给从节点,保证主从复制进入正常状态。

主从节点在建立复制后,它们之间维护着长连接并彼此发送心跳命令。主从心跳判断机制。

  1. 主从节点彼此都有心跳检测机制,各自模拟成对方的客户端进行通信,通过client list命令查看复制客户端信息,主节点的连接状态为flags=M,从节点连接状态为flags=S。
  2. 主节点默认每隔10秒对从节点发送ping命令,判断从节点的存活性和连接状态,可能通过repl-ping-slave-period参数修改发送频率。
  3. 从节点在主线程中每隔1秒发送replconf ack{offset}命令,给主节点上报自身当前的偏移量。

主节点不但负责数据读写,还负责把写命令同步给从节点。写命令的发送过程是异步完成的,也就是说主节点自身处理完写命令后直接返回给客户端,而并不等从节点复制完成。下面我们了解一下异步复制的流程。

  1. 主节点接受处理命令。
  2. 命令处理完之后返回响应结果。
  3. 对于修改命令异步发送给从节点,从节点在主线程中执行复制命令。

上述内容就是本篇中的全部内容,如有不正确的地方欢迎留言,谢谢。

  1. 设计模式 怎么就4篇 赶紧增加

    回复
    1. @刘学勇

      已前写了,但感觉不太好,就没有发表,在草稿存着呢

      回复