Redis的持久化功能在一定程度上保证了数据的安全性,即便是服务器宕机的情况下,也可以保证数据的丢失非常少。通常,为了避免服务的单点故障,会把数据复制到多个副本放在不同的服务器上,且这些拥有数据副本的服务器可以用于处理客户端的读请求,扩展整体的性能
下面会介绍Redis的主从复制配置和实现原理,后续还会有Redis的高可用方案:哨兵机制(Sentinel)、分区集群(Cluster)
1.概念:
主从复制,是指将一台Redis服务 器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slavefollower) ;数据的复制是单向的,只能由主节点到从节点。Master以写为主, Slave 以读为主。默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点) ,但是一个从节点只能有一个主节点。
主从复制的好处:
数据冗余,实现数据的热备份
故障恢复,避免单点故障带来的服务不可用
读写分离,负载均衡。主节点负载读写,从节点负责读,提高服务器并发量
高可用基础,是哨兵机制和集群实现的基础
一般来说,单台Redis最大使用内存不应该超过20G。
电商网站上的商品,-般都是一 次上传,无数次浏览的,说专业点也就是“多读少写"。
主从复制,读写分离! 80% 的情况下都是在进行读操作!减缓服务器的压力!架构中经常使用! 一主二从!
2.主从复制的原理:
Redis的主从复制过程大体上分3个阶段:建立连接、数据同步、命令传播。
Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。下图为级联结构:
建立连接:
这个阶段主要是从服务器发出slaveof
命令之后,与主服务器如何建立连接,为数据同步做准备的过程。
1)在slaveof命令执行之后,从服务器根据设置的master的ip地址和端口,创建连向主服务器的socket套接字连接,连接成功后,从服务器会为这个套接字关联一个专门的处理器,用于处理后续的复制工作
2)建立连接之后,从服务器会向主服务器发送ping命令,确认主服务器是否可用,以及当前是否可用接受处理命令。如果收到主服务器的pong回复说明是可用的,否则有可能是网络超时或主服务器阻塞,从服务器会断开连接发起重连
3)身份验证。如果主服务器设置了requirepass选项,那么从服务器必须配置masterauth选项,且保证密码一致才能通过验证
4)身份验证完成之后,从服务器会发送自己的监听端口,主服务器会保存下来
数据同步:
在主从服务器建立连接确认各自身份之后,就开始数据同步,从服务器向主服务器发送PSYNC
命令,执行同步操作,并把自己的数据库状态更新至主服务器的数据库状态。
Redis的主从同步分为:完整重同步(full resynchronization)和部分重同步(partial resynchronization)。
全量同步:
有两种情况下是完整重同步,一是slave连接上master第一次复制的时候;二是如果当主从断线,重新连接复制的时候也有可能是完整重同步。
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:
- 从服务器连接主服务器,发送SYNC命令;
- 主服务器接收到SYNC(2.8版本之前是PSYNC)命名后,开始fork出一个子进程并执行BGSAVE命令生成RDB文件,并使用缓冲区记录此后执行的所有写命令;
- 主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
- 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
- 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
- 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
- 后期同步会发送自已slave_repl_offset位置,只同步新增的数据,不在全量同步;
完成上面几个步骤后就完成了从服务器数据初始化的所有操作,从服务器此时可以接收来自用户的读请求。
增量同步:
Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程,也可以用于处理断线后重复制的情况,下面先介绍几个用于增量同步的部分:
runid(replication ID),主服务器运行id,Redis实例在启动时,随机生成一个长度40的唯一字符串来标识当前节点
offset,复制偏移量。主服务器和从服务器各自维护一个复制偏移量,记录传输的字节数。当主节点向从节点发送N个字节数据时,主节点的offset增加N,从节点收到主节点传来的N个字节数据时,从节点的offset增加N
replcation backlog buffer
,复制积压缓冲区。是一个固定长度的FIFO队列,大小由配置参数repl-backlog-size
指定,默认大小1MB。需要注意的是该缓冲区由master维护并且有且只有一个,所有slave共享此缓冲区,其作用在于备份最近主库发送给从库的数据
当slave连接到master,会执行PSYNC <runid> <offset>
发送记录旧的master的runid
(replication ID)和偏移量offset
,这样master能够只发送slave所缺的增量部分。但是如果master的复制积压缓存区没有足够的命令记录,或者slave传的runid
(replication ID)不对,就会进行完整重同步,即slave会获得一个完整的数据集副本
PSYNC命令执行完整重同步和部分重同步的流程图:
命令传播:
当完成数据同步之后,主从服务器的数据暂时达到一致状态,当主服务器执行了客户端的写命令之后,主从的数据便不再一致。为了能够使主从服务器的数据保持一致性,主服务器会对从服务器执行命令传播操作,即每执行一个写命令就会向从服务器发送同样的写命令。
在命令传播阶段,从服务器会默认以每秒一次的频率向主服务器发送心跳检测:
<replication_offset>
其中replication_offset
是当前从服务器的复制偏移量,该命令的作用有三个
检测主从服务器的网络连接状态
辅助实现min-slaves
选项
检测命令丢失
Redis主从同步策略:
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
注意:如果多个Slave断线了,需要重启的时候,因为只要Slave启动,就会发送sync请求和主机全量同步,当多个同时出现的时候,可能会导致Master IO剧增宕机。
3.主从复制配置:
使用和配置主从复制是比较简单的,在从服务器slave的配置文件中设置slaveof
选项,或者直接使用slaveof <masterip> <masterport>
命令
这里我使用3台虚拟机来搭建一下,主服务器的ip为192.168.249.20
,两个从服务器的ip分别为192.168.249.21
和192.168.249.21
,端口号都为6379
,具体的配置过程省略:
在从服务器中添加配置slaveof <masterport> <masterport>
选项,在5.0版本中使用了replicaof
代替了slaveof,slaveof
还可以继续使用,不过建议使用replicaof
。如果是使用命令行来复制的话,重启之后会无效;
如果我们需要slave对master的复制进行验证,可以在master中配置requirepass <password>
选项设置密码
那么需要在从服务器中使用该密码,可以使用命令config set masterauth <password>
,或者在配置文件中设置masterauth <password>;