Redis可以实现单机模式下的数据持久化,但解决不了单点宕机问题,一旦单台Redis服务器本身出现系统故障、硬件故障等问题后,就会直接造成数据的丢失。

    要解决此问题,我们可以部署Redis主从复制架构,Redis主从复制也是Redis集群最简单的实现方式,此篇就来看下如何部署Redis主从架构。

    此次实验,笔者准备了3台Rocky主机,IP分别为10.0.0.{8,18,28},主机名分别为RedisServer、slave1和slave2。


  1. 脚本安装Redis

    当前Linux系统中直接通过yum或者apt安装的Redis版本较老,笔者使用脚本进行Redis6.2.2版本的编译安装,脚本内容如下。

实现Redis主从复制_主从复制

实现Redis主从复制_redis_02

实现Redis主从复制_主从复制_03

实现Redis主从复制_数据_04

实现Redis主从复制_数据_05

    脚本执行完毕,检测下端口和Redis服务状态,确保是可用的。

实现Redis主从复制_数据_06

实现Redis主从复制_主从复制_07


  1. Redis主从复制

    主从模式可以实现Redis数据的跨主机备份,在配置主从复制时,从节点也要开启数据持久化并设置和主节点同样的连接密码。

2.1 默认主从状态

    默认情况下,三台主机都是单机模式下的master角色。

实现Redis主从复制_主从复制_08

实现Redis主从复制_redis_09

实现Redis主从复制_主从复制_10

2.2 主从复制的实现

    配置Redis主从复制有两种方式,一种是通过命令行,一种是修改配置文件。

2.2.1 命令行配置

2.2.1.1 主节点写入测试数据

    为了测试同步功能,笔者先在主节点写入一些数据,用于后期查看主从同步功能。

实现Redis主从复制_redis_11

2.2.1.2 启用主从同步

    使用命令行配置主从同步时,需要在从节点上使用replicaof命令指向主节点的IP+端口,查看复制信息时,角色随便变成了slave,但主节点的连接状态确实down。

实现Redis主从复制_数据_12

    此时,需要设置主节点 的连接密码,即主节点在Redis配置文件中设置的requirepass的密码,即可实现主从复制,查看复制信息,主节点的连接状态已经变成了up,查看Redis数据库中的key信息,也已经从主节点同步过来数据。

实现Redis主从复制_主从复制_13

    另一个从节点slave2执行相同命令加入主从复制架构。

实现Redis主从复制_主从复制_14

2.2.1.3 查看主从状态

    主节点上查看复制信息时,已经可以看到自己是master角色,有2个从节点,并能显示从节点的相关信息。

实现Redis主从复制_redis_15

2.2.1.4 查看日志

    主节点或者从节点查看日志可以从节点添加完毕的数据同步过程。

实现Redis主从复制_数据_16

实现Redis主从复制_数据_17

2.2.1.5 测试主从同步

    在主节点查看端口,可以看到Redis服务的6379与两个slave节点的端口进行了持续连接,即可以时刻保持数据同步。

实现Redis主从复制_redis_18

实现Redis主从复制_redis_19

实现Redis主从复制_主从复制_20

    此时,主节点写的数据,两个从节点是可以保持同步的。

实现Redis主从复制_redis_21

实现Redis主从复制_主从复制_22

实现Redis主从复制_数据_23

2.2.1.6 从节点写入测试

    在Redis主从复制中,只有主节点才能进行写操作,从节点无法进行写操作,只能进行读操作。

实现Redis主从复制_redis_24

2.2.1.7 删除主从同步

    从节点上执行replicaof no one命令即可取消主从同步,取消主从同步后,对应主机自动变动master角色,并且之前同步的数据不会丢失。

实现Redis主从复制_redis_25

2.2.1.8 重启自动删除主从复制

    由于是通过命令行添加的主从复制,从节点重启Redis服务后将自动删除之前通过命令行添加的主从复制,与命令行取消主从复制一样,也会保留之前同步过来的数据。

实现Redis主从复制_redis_26

2.2.2 配置文件配置主从复制

    要想做到主从复制关系的持久有效,需要从节点将命令行的内容添加到配置文件中。生产中建议命令行和配置文件同时修改,但不重启从节点Redis服务,等待其出现故障等情况自动重启读取配置文件。

实现Redis主从复制_redis_27

实现Redis主从复制_redis_28

    利用配置文件来进行主从复制时,只是将各节点的主从关系持久保存下来,其他命令都是相同的,笔者就不重复演示。


  1. 主从复制故障与恢复

3.1 从节点故障与恢复

    当从节点出现故障时,只需将Redis客户端指向其它的从节点即可,并不会对整体架构的读操作进行太大影响,即使所有的从节点都出现了故障,也可以直接在主节点进行读操作。当然从节点出现故障后,还是建议尽快进行修复,以减轻其他节点的工作压力。

实现Redis主从复制_主从复制_29

实现Redis主从复制_redis_30

实现Redis主从复制_redis_31

实现Redis主从复制_redis_32

3.2 主节点故障与恢复

3.2.1 模拟主节点故障

    关掉主节点的Redis服务模拟主节点出现故障情况。

实现Redis主从复制_主从复制_33

    登录到从节点查看,主节点的连接状态已经变成了down,由于主从复制架构下,只有主节点才能进行写操作,如果主节点挂掉了,必然会对业务产生影响。

实现Redis主从复制_数据_34

3.2.2 提升新的主节点

    为了减少Redis主从复制架构下主节点故障带来的影响,需要提升某一个从节点为新的主节点。

3.2.2.1 取消主从同步

    例如现在要将slave1提升为新的主节点,则先要在slave1上取消主从同步,此时slave1已经恢复单机状态下的master角色,并可进行写操作。

实现Redis主从复制_主从复制_35

3.2.2.2 其它节点开启主从复制

    slave2将主从复制架构下的主节点信息指向slave2,由于已经在配置文件中添加过masterauth信息,故执行单条命令即可完成主从复制,查看slave1之前写入的name5这个key,已经可以获取对应value值。

实现Redis主从复制_redis_36

3.2.3 原主节点恢复正常

    重启原主节点的Redis服务,模拟服务器故障处理完毕,此时登录Redis可以看到又恢复到单机状态,并且只有4个数据。

实现Redis主从复制_主从复制_37

    如果将原主节点变成现有主从架构下的从节点,则可从现主节点(即slave1)同步name5这个key;但如果要保持原主节点不变,则要将现在的主从架构各节点都指向原主节点,并且之前写入的name5这个key也将丢失。

    以依旧保持RedisServer主机为主节点为例,从节点执行主从复制命令时的顺序带来的效果不同,如果先在slave2上执行命令,则slave2变成RedisServer的从节点;如果先在slave1上执行,则可完成级联复制,slave2无需执行任何命令,仍然是slave1的从节点,并可通过slave1来间接同步数据。

实现Redis主从复制_数据_38

实现Redis主从复制_数据_39


  1. 主从复制优化

4.1 主从复制过程

    Redis主从复制分为全量复制同步和增量复制同步。

4.1.1 全量复制同步

    Redis主从复制全量复制同步过程如下图所示:

实现Redis主从复制_redis_40

    首次进行主从同步使用的是全量同步,主从同步可以让从节点通过主节点进行数据同步,而且从节点还可以再有自己的从节点,即以上所提到的级联复制架构。

    Redis的主从同步是非阻塞的,主节点在收到从节点的psync命令(2.8版本前为SYNC)后,会fork一个子进程在后台执行bgsave命令,并将新写入的数据暂时先写到缓冲区,bgsave完成后将生成的RDB文件发送给从节点,然后主节点再将缓冲区的内容以Redis协议格式再全部发送给从节点。

    从节点先删除旧数据,将接收到的RDB文件载入内存,再加载所有收到缓冲区的内容,从而完成一次完整的数据同步。

    Redis全量复制一般发生在从节点首次初始化阶段,这是从节点需要将主节点上的所有数据都复制一份。

4.1.2 增量复制同步

    Redis主从复制增量复制同步过程如下图所示:

实现Redis主从复制_数据_41

    在全量同步完成之后,如果还需要进行数据的同步,从节点只要发送当前的offset位置(类似于MySQL二进制日志记录的位置)给主节点服务器,然后主节点根据相应的位置将之后的数据(包括写在缓冲区的挤压数据)发送给从节点,并再次将其保存至从节点内存即可。

4.1.3 Redis主从同步完整过程

    ①从节点连接主节点,发送PSYNC命令;

    ②主节点接收到PSYNC命令后,开始执行bgsave命令生成RDB文件,并使用缓冲区记录此后执行的所有写命令;

    ③主节点bgsave命令执行完毕,向所有的从节点发送RDB文件,并在发送期间继续记录被执行的写命令;

    ④从节点收到RDB文件后丢弃所有旧数据,载入收到的RDB文件至内存;

    ⑤主节点发送RDB文件后,开始向从节点发送缓冲区中的写命令;

    ⑥从节点完成对RDB文件的载入,开始接收命令请求,并执行来自主节点服务器缓冲区的写命令;

    ⑦从节点后期的同步会先发送自己offset位置,只同步新增的数据,不再做全量同步。

4.2 主从复制注意事项

4.2.1 避免全量复制

    ①第一次全量复制不可避免,后续的全量复制可以利用小主节点(内存小),在业务低峰时进行全量复制;

    ②主节点在重启后会导致RUNID发生变化,可能会触发全量复制,可以利用故障转移,例如哨兵或者集群;

    ③复制积压缓冲区不足时,如果主节点新生成的数据过大,在从节点恢复与主节点的连接后可能会导致全量复制,解决方法是将repl-backlog-size值调大。

4.2.2 避免复制风暴

    ①单主节点复制风暴:当主节点重启后,多个从节点会同时从主节点复制数据,带来复制风暴,解决方法是更换复制拓扑。

实现Redis主从复制_主从复制_42

    ②单机多实例复制复制风暴:当服务器出现宕机,并修缮完毕后,会进行大量的全量复制,引发复制风暴,解决方法是主节点分散多机器。

实现Redis主从复制_数据_43


  1. 常见主从复制故障

5.1 主节点密码不正确

    即主节点在Redis配置文件中设置的requirepass部分,从节点在执行主从同步命令时或者修改配置文件时未添加正确,则会导致无法建立主从同步关系。

5.2 Redis版本不同

    不同的Redis大版本之间会存在兼容性问题,例如不同节点有使用3版本的,有使用4版本的,各节点之间应尽量保持Redis版本的一致性。

5.3 无法远程连接

    在开启了安全模式下,没有在配置文件中设置bind地址或者未设置密码,则会无法进行远程连接。

5.4 主从节点配置不一致

    ①主从节点的maxmemory设置不一致,主节点内存大于从节点内存,则可能会导致主从复制时的数据丢失现象;

    ②rename-command命令不一致,例如在主节点上定义了flushall或flushdb命令,而没有在从节点上进行相同的定义,则执行flushall或flushdb命令不能同步数据。