redis之主从复制原理解析

2022-09-05 09:05:40

一、redis主从复制的作用

redis的定位是一个高可用的数据服务器,可是在实际生产环境下,单机的redis服务器是无法满足真正意义上的高可用性的。

第一,单机的redis服务器很容易发生单点故障,即使redis提供了各种持久化的方法来避免数据的丢失,但是物理上的故障(硬盘损毁等)还是无法完全避免的。

第二,如果对单台机器的性能进行纵向拓展,无论是CPU,内存还是磁盘容量都很容易达到瓶颈,无法满足实际需求。

针对这些问题,redis提供了复制(replication)的功能,通过"主从(一主多从)"和"集群(多主多从)"的方式对redis的服务进行水平扩展,用多台redis服务器共同构建一个高可用的redis服务系统。

简单来说就两点:

(1)为数据提供多个副本,实现高可用
(2)实现读写分离

二、redis主从复制介绍

在redis的复制概念模型中,分为"主(master)"和"从(slave)"两种角色类型的服务器,从服务器"服从"主服务器。主服务器既可以读也可以写,而从服务器原则上只允许读操作(通过修改配置,从服务器也可以执行写入操作),同时负责接收和同步主服务器上的数据。主服务器和从服务器是一对多的关系,从服务器也可以拥有从服务器,以此类推。

可以看到主从结构下的redis服务器集群节点的拓扑结构是一棵树。
在这里插入图片描述
 使用了主从结构的redis系统,一般是读写分离的:"主库负责写入,在写入的同时和从库进行数据的同步;而从库负责读取操作。"

一主多从的结构下,不会出现单点故障,同时可用性也得到了保障。由于负责读取的从库相对较多,因此很适合读多写少(例如:电商)的场景。

使用redis的主从复制功能比较简单,只需要在从服务器启动的配置文件中添加slaveof “IP” "PORT"配置即可,同时redis也允许其它的方式来实现这一目的(启动时命令行参数、redis命令等)。可以通过info replication来查看当前redis服务器在主从复制中的状态。

6381端口的从库状态:
在这里插入图片描述
6379端口的主库状态:
在这里插入图片描述

三、redis主从复制原理

1、从服务器初始化
 当从服务器启动时,会向主服务器发送SYNC命令,请求同步数据。主服务器接收到消息之后,进行RDB持久化,并生成一个快照文件;与此同时,主服务器会将生成快照期间新执行的命令缓存起来。在快照文件生成完毕之后,主服务器将RDB快照文件和缓存下来的命令一并发送给从服务器,从服务器首先载入接收到的RDB快照文件,接着执行被缓存下来的新命令,完成主从数据的初始化同步操作。

2、从服务器保持同步
从服务器在同步完成之后,主服务器接收到的所有命令都会异步的发送给从服务器用来保持主从数据的一致性。

3、从服务器故障后处理
当从服务器崩溃之后,重启之后进行初始化,会自动的同步主服务器的数据。在redis的2.8版本之后,redis采用了"增量复制"的方式优化了从服务器的初始化同步数据的过程。

4、主服务器故障后处理
当主服务器崩溃之后,首先需要手动的选择一个从服务器升级为主服务器(需要手动调整所有相关的从服务器),然后启动之前已经崩溃的主服务器作为从服务器回到系统中。

可以看到,redis在主服务器崩溃之后需要繁琐的人工干预来恢复服务,特别是在主数据库禁止了持久化之后,上述步骤不能错乱,否则会导致主数据库重启后恢复了错误数据,进而导致从数据库也同步错误数据这一灾难性后果。为此,redis提供了哨兵机制,用于自动化的监控和维持分布式redis系统的良好运转。

接下来介绍全量复制和部分复制的原理:

1、全量复制

用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作,当数据量较大时,会对主从节点和网络造成很大的开销
在这里插入图片描述
全量复制过程:

(1)Redis内部会发出一个同步命令,刚开始是Psync命令,Psync ? -1表示要求master主机同步数据
(2)主机会向从机发送run_id和offset,因为slave并没有对应的 offset,所以是全量复制
(3)从机slave会保存主机master的基本信息
(4)主节点收到全量复制的命令后,执行bgsave(异步执行),在后台生成RDB文件(快照),并使用一个缓冲区(称为复制缓冲区)记录从现在开始执行的所有写命令
(5)主机发送RDB文件给从机
(6)发送缓冲区数据
(7)刷新旧的数据。从节点在载入主节点的数据之前要先将老数据清除
(8)加载RDB文件将数据库状态更新至主节点执行bgsave时的数据库状态和缓冲区数据的加载。

全量复制开销:

(1)主节点需要bgsave
(2)RDB文件网络传输占用网络io
(3)从节点要清空数据
(4)从节点加载RDB
(5)全量复制会触发从节点AOF重写

2、部分复制

部分复制是Redis 2.8以后出现的,用于处理在主从复制中因网络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发丢失数据给从节点。因为补发的数据远远小于全量数据,可以有效避免全量复制的过高开销,需要注意的是,如果网络中断时间过长,造成主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制。
在这里插入图片描述
部分复制过程:

(1)如果网络抖动(连接断开 connection lost)
(2)主机master 还是会写repl_back_buffer(复制缓冲区)
(3)从机slave 会继续尝试连接主机
(4)从机slave 会把自己当前 run_id和偏移量传输给主机 master,并且执行 pysnc 命令同步
(5)如果master发现你的偏移量是在缓冲区的范围内,就会返回continue命令
(6)同步了offset的部分数据,所以部分复制的基础就是偏移量 offset。

服务器运行ID(run_id):每个Redis节点(无论主从),在启动时都会自动生成一个随机ID(每次启动都不一样),由40个随机的十六进制字符组成;run_id用来唯一识别一个Redis节点。 通过info server命令,可以查看节点的run_id。

四、redis哨兵机制

1、哨兵的介绍
redis的设计者为了让redis能够在主从模式下实现故障恢复的自动化,为此提供了redis的哨兵功能。哨兵是一个独立于数据服务器的进程,用于监控redis数据服务器的状态,当主从模式下最关键的主服务器出现故障时,能够被哨兵自动的察觉。同时哨兵会在剩余的从服务器中"选举"出新的主服务器,达到自动化恢复系统服务的目的。

2、哨兵的使用
redis提供了redis-sentinel脚本用于部署哨兵,启动时通过指定的哨兵配置文件来对哨兵的行为进行灵活的控制。哨兵的配置文件中至少需要包含被哨兵监控的主服务器IP、端口、投票决定数目,当然也可以配置诸如down-after-milliseconds(发送ping命令的时间间隔,用于监听)等选项。

sentinel monitor"master_name""IP""PORT"   
down-after-milliseconds"milliseconds"("milliseconds"大于1000时,默认为1000)

3、哨兵的工作方式
哨兵启动时会与主服务器建立连接,并且间接的获得所属从服务器信息,完成哨兵的初始化。哨兵初始化完成之后,会周期性的和主从服务器、其它哨兵节点(通过消息频道的订阅/发布)进行通信。

哨兵每10秒会向所有服务器发送一次INFO命令,获得相关redis服务器的当前状态以便决定是否需要故障恢复。

当一个哨兵在down-after-milliseconds规定时间内未收到主服务器的响应,则当前哨兵"主观“认为主服务器下线,同时和监视当前系统的其它哨兵进行投票决定,当超过当前哨兵配置中投票决定的数目时,则当前哨兵”客观"认为主服务器下线,哨兵集群会选举出领导哨兵来进行主从服务器集群主从状态的切换(使用Raft算法)。

五、redis在开发运维中常见的问题

1、读写分离
(1)复制数据存在延迟(如果从节点发生阻塞)
(2)从节点可能发生故障

2、主从配置不一致
(1)例如maxmemory不一致,可能会造成丢失数据
(2)例如数据结构优化参数不一致:造成主从内存不一致

3、规避全量复制
(1)第一次全量复制不可避免,所以分片的maxmemory减小,同时选择在低峰(夜间)时,做全量复制。
(2)复制积压缓冲区不足
增大复制缓冲区配置rel_backlog_size

例如如果网络中断的平均时间是60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见,可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。

4、复制风暴
master节点重启,master节点生成一份rdb文件,但是要给所有从节点发送rdb文件。对cpu,内存,带宽都造成很大的压力。

六、总结

1、乐观复制策略
redis的主从复制采用的是乐观复制的策略,在一定的时间内允许主从服务器的数据不完全一致,但是保持主从数据库数据的最终一致性(按照CAP定理,放弃了C(强一致性))。

这意味着redis主从服务器之间的数据复制操作时异步的,主服务器不等待从服务器返回复制的结果,可以立即处理新的写入命令。这一策略使得主服务器的性能在复制时不会受到太大影响,但是从服务器会出现短时间内数据不一致的情况。redis允许用户配置主库的min-slaves-to-write(代表至少N台从服务器完成复制,才允许主服务器写入)和min-slaves-max-lag(允许从服务器断开连接的时间)这两个配置项来控制分区中数据不一致的影响。

2、和集群的区别
redis的主从复制特性为redis带来了很高的读取可用性,但是对于海量数据的持久化存储是力不从心的。因为主从复制结构下,任意的节点都保存了100%的存储数据,所以能够存储的数据规模还是受限于单例服务器存储容量的大小。

为此,在单主多从结构的基础上,redis还提供了集群特性。通过将存储数据合理的分片存储在不同的redis节点上,通过集群水平扩容之后的redis集群拥有了极高的读写可用性和分区容错性。理解redis的主从复制原理是理解更为复杂的集群特性的基础。

  • 作者:故明所以
  • 原文链接:https://blog.csdn.net/weixin_43520450/article/details/107550548
    更新时间:2022-09-05 09:05:40