redis主从复制详解

1.概述

Redis作为一个内存数据库,使用主从架构的最核心的目的便是提供数据冗余备份,以防止单个Redis节点挂掉之后其中的数据也被丢失,主从复制是高可用的基础,在此基础上,可以实现读写分离,哨兵机制等模式。作为冗余备份,主从节点最重要的工作便是数据同步。这篇文章介绍一下Redis的数据同步策略,包括主从节点首次建立连接后的全量复制以及从节点短暂断连后的数据部分复制。

2.原理及作用

主从复制,是指将一台Redis服务器的数据复制到其他的Redis服务器,前者称为主节点(master/leader),后者称为从节点(slave/follower)。一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点,同时每个从节点也可以是别的从节点的父节点,即主从节点连接形成树结构。

主从复制的发起都是在子节点发起,当slave节点使用salveof masterIp masterPort后,slave与master节点的数据复制过程如下图所示;

主从结构中数据的复制是单向的,只能由主节点复制到从节点,所有的内存变更,即数据的增删改都只能在主节点上进行,从节点通过同步的方式完成修改。默认情况下,从节点对非Master节点客户端是只读的。主从复制有以下几个用途:

  • 数据冗余
    跟单节点RDB和AOF作用一样,实现数据备份,区别在于备份到本节点还是其他节点,主从结构单台节点挂了之后,其上节点上的数据不丢失。

  • 故障恢复
    当主节点出现问题时,从节点可以被提升为主节点继续提供服务,实现快速的故障恢复;

  • 负载均衡
    在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。

3.复制方式

Redis主从复制有全量复制和部分复制两种方式。全量一般用于初次复制场景,Redis早期支持的复制功能只有全量复制,它会把主节点全部数据一次性发送给从节点,当数据量较大时,会对主从节点和网络造成很大的开销。部分复制通过对比主从节点的复制偏移量,可以判断主从节点数据是否一致,复制部分偏移量的数据。

  • 全量复制
    Redis采用了RDB和AOF两种持久化方式,当Redis重启后便可以从RDB文件或者AOF文件中恢复出数据。而全量复制的核心就是把Master节点当前的数据全部发送给子节点,相当于把Master节点的RDB文件或者AOF文件发给Slave节点。这样Slave节点接收到文件之后就可以从文件中恢复出Master节点的数据。当然,为了保证主从节点一致,Slave节点从持久化文件中恢复数据之前首先应该清空自己内存中的所有数据。全量复制步骤如下:

    整个过程每一步都是耗时间的IO操作,比如Master节点在T1时刻开始RDB文件的生成,一直到T2时刻Slave节点才能完成数据载入。在网络环境较差或者IO能力较弱的情况下,上述的操作不仅耗时久,而且会因此导致主从节点数据延迟比较大。

  • 命令传播+增量复制
    命令传播是Master节点每处理完一个写命令都会把命令发送给所有的子节点,而每个子节点接收到Master的命令后,会在处理完之后继续发送给自己的子节点。需要注意的是,Redis的发送命令是异步的操作。即Master节点处理完客户端的命令之后会立马向客户端返回结果,而不会一直等待所有的子节点都确认完成操作后再返回以保证Redis高性能。有一种情况就是,某个子节点因为某些异常与Master短暂的断连了N秒,子节点恢复连接之后该如何同步这N秒数据呢?Redis的做法是开辟一个缓冲区(默认大小是1M),每次处理完命令之后,先写入缓冲区repl_backlog, 然后再发送给子节点。这就是增量复制(也叫部分复制)。但是缓冲区能保存的命令有限,只能至多保存的命令长度为repl_backlog_length,如果某个子节点落后当前最新命令的长度大于了repl_backlog_length,那么就会触发全量复制。

4.主从测试

实验环境:

操作系统 IP地址 M/S
centos7 192.168.64.138 Master
centos7 192.168.64.139 Slave

修改Slave的配置文件redis.conf,修改参数slaveof为:

slaveof 192.168.64.138 6379

分别启动Master,Slave,启动后Master,Slave输出:

测试Master上写入数据:

#写入数据
192.168.64.138:6379> set a 1
OK
192.168.64.138:6379> set b 2
OK
192.168.64.138:6379> set c 3
OK

测试Slave上获取数据:

#获取数据
192.168.64.139:6379> get a 
"1"
192.168.64.139:6379> get b 
"2"
192.168.64.139:6379> get c 
"3"

可以看到Master上的数据已经同步到Slave上了。各位如果觉得还有点意义,烦请点一下推荐,加个关注,互相交流。

posted @ 2020-03-10 16:20  风行天下12  阅读(628)  评论(0编辑  收藏  举报
返回顶部