Redis主从复制

上篇文章中,我们了解了 Redis 两种不同的持久化方式,Redis 服务器通过持久化,把 Redis 内存中持久化到硬盘当中,当 Redis 宕机时,我们重启 Redis 服务器时,可以由 RDB 文件或 AOF 文件恢复内存中的数据。
不过持久化后的数据仍然只在一台机器上,因此当硬件发生故障时,比如主板或 CPU 坏了,这时候无法重启服务器,有什么办法可以保证服务器发生故障时数据的安全性?或者可以快速恢复数据呢?这里就需要用到Redis另一种机制:主从复制

一、说明:Redis 的主从复制机制是指可以让从服务器(Slave)能精确复制主服务器(Master)的数据。一台 Master 服务器对应一台Slave服务器也可以对应多台 Slave 服务器。Master节点和Slave节点在不同服务器,主从复制和持久化可同时进行。

二、作用:

1,数据备份:主从复制实现了数据的热备份,提高数据的安全性

2,故障恢复:当主节点发生问题不能提供服务时,从节点可以提供服务,保证Redis集群的可用性
3,负载均衡:在主从复制的基础上,可以实现读写分离,主节点负责写操作,从节点负责读操作,在写少读多的场景下,可以使用该模式大大提高Redis的并发量
4,Redis高可用:主从复制是实现哨兵和集群的基础,主从复制是Redis高可用的基石
三、主从复制实现

准备一台虚拟机,配置3个Redis:10.132.50 6677  10.132.50 6678   10.132.50 6679。执行命令slaveof  10.132.50 6677 即可。6677为Master,6678和6679为Slave。

四、数据同步

Redis2.8之前,从节点向主节点发送sync命令请求数据同步,此时的同步时全量复制,Redis2.8之后从节点发送psync命令进行数据同步,此时根据主从节点当前状态不同,同步的结果可能是全量复制或者部分复制。

全量复制:用于初次复制或其他无法部分复制的情况,将主节点中的所有数据都发送给从节点,是一个很重的操作。
部分复制:用于网络中断等情况的复制,只将中断期间主节点的写操作发送给从节点,相比全量复制比较高效,如果连接断开时间过长,导致主节点没有完整的保存断开时间内的数据,那么还是会使用全量复制。

五、同步机制

当一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave ,包括客户端的写入、key 的过期或被逐出等等。

当 master 和 slave 之间的连接断开之后,因为网络问题、或者是主从意识到连接超时, slave 重新连接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流。

当无法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,例如 master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave 。
六、全量复制原理(上篇文章中讲到的 持久化)

(1) slave判断无法进行部分复制,向master发送全量复制请求,或slave发送部分复制,master判断无法进行全量复制;
(2) master接收到全量复制指令之后,运行bgsave,在后台生成RDB文件,并生成一个缓冲区(复制缓冲区),记录从现在开始执行的所有写命令;
(3) master的bgsave执行完毕之后,将RDB文件发送给slave,slave首先清除自身旧数据,然后载入接收的RDB文件,将数据库状态更新至master执行bgsave时的数据库状态;
(4) master将上文提到的复制缓冲区中所有写命令发送给slave,slave执行这些写命令,将数据库状态更新至master最新状态;
如果slave开启了AOF,则会触发bgrewriteaof操作,从而保证AOF文件更新到最新状态。
七、部分复制原理

因为全量复制损耗太大,Redis2.8版本开始提供部分复制,用于处理网络中断时的数据同步。部分复制实现主要依赖于三个重要的概念:复制偏移量,复制积压缓冲区,服务器运行ID

1,复制偏移量(offset)

主节点和从节点分别维护一个复制偏移量(offset),代表的是master向slave传递的字节数。这两个数值相同说明数据就一样了。主节点每次向从节点传播N个字节数据时,主节点的offset增加N;从节点每次收到主节点传来的N个字节数据时,从节点的offset增加N。例如,如果主节点的offset是1000,而从节点的offset是500,那么部分复制就需要将offset为501-1000的数据传递给从节点。而offset为501-1000的数据存储的位置,就是下面要介绍的复制积压缓冲区

2复制积压缓冲区

复制积压缓冲区由主节点创建、维护、固定长度、先进先出。无论主节点有几个从节点,都只需要一个复制积压缓冲区,默认大小为1M

         在命令传播阶段,主节点除了将写命令发送给从节点外还会发送一份给复制积压缓冲区,作为写命令的备份,除了存储写命令,复制积压缓冲区中还存储了其中的每个字节对应的复制偏移量(offset)。由于复制积压缓冲区定长且是先进先出,所以它保存的是主节点最近执行的写命令;时间较早的写命令会被挤出缓冲区。
         由于该缓冲区长度固定且有限,因此可以备份的写命令也有限,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。反过来说,为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小(通过配置repl-backlog-size)

从节点将offset发送给主节点后,主节点根据offset和缓冲区大小决定能否执行部分复制:

  • 如果offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制;
  • 如果offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制

3,服务器运行ID(runid)

主从节点初次复制时,主节点将自己的runid发送给从节点,从节点将这个runid保存起来;当断线重连时,从节点会将这个runid发送给主节点;主节点根据runid判断能否进行部分复制:

如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使用部分复制(到底能不能部分复制还要看offset和复制积压缓冲区的情况);
如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不是当前的主节点,只能进行全量复制。主节点重启之后runid会发生变化,在Redis4.0之后可以使用故障转移的方式处理,使用集群或者哨兵模式
八,命令传播阶段

1,主->从:PING

每隔指定的时间,主节点会向从节点发送PING命令,这个PING命令的作用,主要是为了让从节点进行超时判断。

PING发送的频率由 repl-ping-slave-period 参数控制,单位是秒,默认值是10s。

2,从->主:REPLCONF ACK

在命令传播阶段,从节点会向主节点发送REPLCONF ACK命令,频率是每秒1次;命令格式为:REPLCONF ACK {offset},其中offset指从节点保存的复制偏移量。

Redis哨兵机制

一、Redis分片

            如果只使用一台Redis保存业务中所有缓存数据,当这台Redis宕机将影响整个服务。我们应该采用Redis分片,假设之前单台Redis保存9个G的数据,如果我们使用三台,每台就只需维护3个G,每个节点再增加两个从节点,当主节点宕机时,启用从节点工作,那Redis是如何判断使用哪个从节点作为新的主节点继续为我们服务呢?就是我们接下来要讲的Redis Sentinel(Redis 哨兵)。

二、Redis Sentinel流程图

三个定时任务监听

2.1 每10S一个info

每10秒每个sentinel节点会对master和slave发送一个info命令,一是为了发现slave节点,二是为了确认主从关系

rediscluster 一台宕机 redis主机停多久,从机变主_Redis

2.2 每2秒交换信息 

每2秒每个sentinel通过master节点的channel交换信息(pub/sub),相当于一个sentinel的交互平台,交互对master/slave状态的监听情况和自身的信息。通过一个名为__sentinel__:hello的频道交互,每个sentinel节点都会订阅这个频道

rediscluster 一台宕机 redis主机停多久,从机变主_redis_02

2.3 每秒1ping

每一秒每个sentinel节点对其他sentinel和redis执行一次ping,这一步基于第一步sentinel掌握redis的master和slave节点的状况,基于第二步sentinel节点知道其他的sentinel节点,对他们进行心跳检测,判断是否在正常工作。

Sentinel节点会去监控Redis中Master和Slave的运行状态,判断是否可用,哨兵一般为奇数个,采取投票机制,当Master宕机,哨兵就会从Slave中选举出新的Master,通知其余的slave有新的master产生,通知客户端master发生变化。并且客户端不再直接操作Redis的Master或者Slave节点,而是去访问Sentinel节点,我们的客户端不关心谁是Master而是Sentinel告诉客户端谁是Master,后台Master切换了,客户端也不会受到影响。

三、哨兵配置

Redis当中有个专门配置哨兵的配置文件 sentinel.conf,具体配置这里就不说了,自行查找资料。