【Redis】主从复制之读写分离&原理&实战

由于*问题,slave更改为了replica

Redis默认采用异步复制的持久化方案(RDB),具备低延迟、高性能的特点。这是大多数Redis的自然复制模式。
主从复制(master-replica)-读写分离这是基于RDB持久化方案的全量数据复制模式。

1.主从复制-读写分离介绍

为了解决高并发场景下Redis的性能问题,需要对单例Redis进行横向扩展;我们都知道在缓存中读的并发量要远远大于写的并发量。所以就产生了一种读写分离的方法:
将读和写分开,master节点可以进行读写操作,而slave节点只能进行读操作(conf文件可以修改),因此读写分离是一种基于RDB持久化方案的主从架构。

【Redis】主从复制之读写分离&原理&实战

2.读写分离核心流程

首先需要从slave节点初始化进行分析,因为slave节点只能进行读操作,所以它如何拥有初始数据是第一步。

  • 当salve节点初始化时会首先ping向master节点,如果ping通,salve就会把master上的rdb文件复制到slave节点,然后加载到内存中。
  • 后续当master节点有写操作时,master会将相同操作命令传输给salve节点,然后salve进行执行即可。
  • 【Redis】主从复制之读写分离&原理&实战

3.三种工作机制

  • 当master和slave链接良好时,master向slave发送命令流来完成salve更新;
  • 当master和salve链接中断时,由于网络原因或master和salve检测超;salve将尝试重新连接并尝试进行部分重新同步,这意味着同步的是断开连接那段时间的命令流
  • 当无法进行部分重新同步时,salve将进行全部重新同步。这涉及了一个更复杂的过程,需要master创建所有的快照并发给salve。

4.主副本之间如何进行协商的?

试想master每向Redis副本发送一次命令流,是否需要等待副本处理完成?(因为副本可能由于某种原因没有处理完这个命令流)
答:这是不需要的,副本会定期确认与master接收的数据量。所以master知道副本已经处理了哪个命令,这具有可选的同步复制。

5.Redis复制的特点

Ⅰ.Redis复制在主控端是非阻塞的(异步复制),意味着当一个或多个副本进行同步数据时,master仍然可以进行数据查询。

Ⅱ.Redis复制在副本也是非阻塞的(异步复制),在副本执行同步时,仍然可以被查询。但当副本进行初始化时,需要删除本身的旧数据集加载新数据集,这短暂的期间是不能被客户端连接的。在Redis4.0以后,允许在conf进行配置删除旧数据集发生在不同的线程中,但是加载新数据集仍发生在主线程中,所以这个时间段仍是阻塞的。

Ⅲ.一个master可以连接多个副本,一个副本也可以连接多个副本,类似于级联结构。

Ⅳ.避免了master将整个数据写入磁盘的成本。

6.Redis复制的工作原理

每个Redis实例都有Replication ID,每个主机也存在一个偏移量,该偏移量随着主机向副本发送命令流的字节而增加。

当副本要连接主机时,会通过PSYNC命令发送它的旧主机Replication ID和Offset。这样主机只需要向副本发送增量部分。

发送Offset(偏移量)我们应该都明白它是为了定位缓冲区发送的起始位置,向副本发送它缺少的那部分数据。那Replication ID有什么用呢?
其实这是为了让主机将自身的Replication ID与副本发送的Replication ID做对比,判断是否相同,如果相同则可以进行增量复制。如果不相同,所以主机已经被更换,需要进行全量复制。

完全同步的工作流程:

主机生成RDB文件,在这个同时缓冲从客户端接收到的新的写命令;主机向副本发送RDB文件,副本将其保存在磁盘并加载到内存中;最后主机将所有缓冲的命令发送给副本。

总结:
Redis在进行全量同步时,master会将内存数据通过bgsave落地rdb文件;同时将接收到的客户端写指令存放到复制缓冲区中。当rdb快照构建完毕之后,master会将rdb和复制缓冲队列中的数据全部发送给replica(副本),可以看出全量同步对系统的性能和资源访问造成影响。
在Redis2.8之前,Redis只支持全量复制;2.8之后引入了PSYNC,增加了一个复制积压缓冲,master在将写指令发送给replica之后,也会在复制积压缓冲存放一份。当由于网络波动导致master与replica连接断开并重新连接时,replica会向master发送replid(复制id)和偏移量,如果master的replid和副本发送的replid相同并且偏移量仍在复制积压缓冲,则master使用增量复制。
Redis4.0之后,引入了PSYNC2,这是对PSYNC的优化,额外加入了一个replid2。每个Redis实例启动之后都会被分配一个长度为40的随机字符串最为replid的初始值,当replica连接master之后,会将master的replid替换自己的replid;replid2会存储上次主机的replid,这样一来如果master发送变动,则master的replid与replica的replid或者replid2相同,仍然可以使用增量复制。

7. 主从复制-读写分离实战

模拟三台Redis服务器,一台6379为主机,另外的6380和6381为副本。

1.首先在Linux服务器下载安装Redis服务

下载安装包:wget https://download.redis.io/releases/redis-6.2.6.tar.gz
解压:tar -zxvf redis-6.2.6.tar.gz
编译:make
安装:make PREFIX=/path install (path为安装路径)

安装之后会发现只有一个bin目录。

2.建立相应的文件保存数据、日志、配置文件

mkdir -p /opt/redis/data
mkdir -p /opt/redis/conf
mkdir -p /opt/redis/
touch redis-6379.conf
touch redis-6380.conf
touch redis-6381.conf

【Redis】主从复制之读写分离&原理&实战
【Redis】主从复制之读写分离&原理&实战

3.将redis解压目录下的redis.conf文件复制一份到/opt/redis/conf

复制:cp redis.conf /opt/redis/conf
重命名:mv redis.conf redis-common.conf

【Redis】主从复制之读写分离&原理&实战
4.修改redis-common.conf配置文件
点击ESC->输入:/搜索词 ,即可进行搜索,键盘点击n表示寻找下一个

(1)修改protected-mode的值为no
【Redis】主从复制之读写分离&原理&实战
(2)修改daemonize的值为yes:表示后台启动redis
【Redis】主从复制之读写分离&原理&实战
(3)注释掉bind(注释掉表示所有的都可以访问)
【Redis】主从复制之读写分离&原理&实战
(4)注释掉port
【Redis】主从复制之读写分离&原理&实战
(5)注释掉logfile
【Redis】主从复制之读写分离&原理&实战
(6)注释掉dbfilename
【Redis】主从复制之读写分离&原理&实战
(7)修改目录
【Redis】主从复制之读写分离&原理&实战
(8)打开masterauth(从服务器访问主服务器所需要的密码)
【Redis】主从复制之读写分离&原理&实战
(9)注释掉pidfile
【Redis】主从复制之读写分离&原理&实战

5.编辑redis-6379.conf、redis-6380.conf、redis-6381.conf

最后一个slaveof表示主机地址,这里的6379为主机,所以不需要配置。
【Redis】主从复制之读写分离&原理&实战
【Redis】主从复制之读写分离&原理&实战
【Redis】主从复制之读写分离&原理&实战

6.启动

./redis-server /opt/redis/conf/redis-6379.conf
./redis-server /opt/redis/conf/redis-6380.conf
./redis-server /opt/redis/conf/redis-6381.conf

使用ps -ef|grep redis进行查看进程
【Redis】主从复制之读写分离&原理&实战
7.测试

复制三个窗口,连接三个客户端,输入info replication查看信息。

上一篇:Redis 事务和乐观锁


下一篇:20 道 Redis 面试题,面试官能问的都被我整理了