一、前言
通过 Redis 的持久化功能,保证了 Redis 在宕机重启的情况下也不会丢失(或者丢失极少部分)数据。但是这只局限在单机情况下。如果这台服务器发生了物理故障、磁盘故障或者磁盘损坏等问题仍然会发生数据丢失。为了避免单点故障的问题、通常的做法就是将数据库复制多个副本部署在不同的服务器上、这样一台或者某几台服务器出现故障、其它服务器仍可以对外提供数据。对此Redis为我们提供了复制(replication)的功能、当一台数据库数据发生变化后将自动同步到其它的数据库中。
Redis 的复制针对主从架构而设计的这里如果对主从架构还不太了解的建议就先不要往下看了,花点半个小时去简单的了解下Redis 的主从架构模式。
纵观 Redis 的主从复制原理我们可以将其抽象剥离成三个步骤进行理解。
题外话、我们在学习、理解枯燥和乏味的算法或者技术原理时建议大家先总体的过下流程之后将其抽象成一个个简单的模型去理解、这样降低了学习和理解的难度。
1. 主从(master < ---- > slave)之间建立连接阶段。
2. 数据同步(复制)阶段
3. 命令传播阶段
二、复制原理
2.1 建立连接阶段
Redis 主从建立连接阶段其实很简单,无非就是确认双方的身份建立连接。
和我们➕某个心动女孩的微信一致。确认是自己喜欢的,想法设法的搞到微信号、发送好友申请、美眉确认、同意加好友、双方将微信号保存到彼此的好友列表中、彼此就建立起了联系。
直接上图吧!
2.2 数据同步阶段
废话不多少直接上图干起
数据同步阶段Master的说明
1、如果Master的数据量过大、数据同步阶段应避开流量高峰阶段、避免造成Master的阻塞、影响正常业务的运行。
2、复制缓冲区大小设置的不合理、会造成数据溢出。如果进行全量复制时间过长、在进行部分复制时发现数据已经丢失的情况会进行二次全量复制(看下增量复制和全量复制的时机)、这样就导致Slave陷入一个死循环状态。
repl-backlog-size: ??MB
3、Master单机内存占主机内存不宜过大、建议在50% - 70% 左右、留下 30 % - 50% 内存用于执行bgSave 和创建缓冲区。
数据同步阶段Slave 的说明
1、为了避免Slave在进行全量同步、部分(增量)同步阶段导致服务响应阻塞或者数据不同步、建议关闭此期间对外提供服务。
slave-server-stale-date: yes|no
2、数据同步阶段 Master 向 Slave 发送信息可以理解为Master 是Slave的一个客户端、主动向Slave 发送命令。
3、当多个Slave 同时向Master 发送数据同步请求时、发送的RDB文件增多、会对网络宽带造成巨大冲击,如果Master网络宽带不足、建议根据自身业务情况、适量错峰同步。
4、Slave过多时建议调整拓扑结构、由一主多从调整为树形结构、中间节点即是Master 也Slave 。注意当使用树形结构时由于层级深度、导致层级越深的节点和Master的数据延迟越大、会导致一定时间内出现数据一致性问题、使用时根据自身业务进行考量。
2.3 命令传播阶段
命令传播阶段就是为了实时保证主从数据一致的过程也就是数据同步过程。
当Master数据库状态被修改后,导致主从数据库状态不一致此时就需要让主从数据库的状态同步到一致的状态,同步的动作就称为命令传播。
Master 将接收到的数据变更命令会发送给Slave、Slave接收到命令后进行执行命令。
命令传播阶段的复制情况
- 命令传播阶段出现断网情况
1. 网络闪断闪连: 忽略
2. 短时间网络中断: 部分(增量)复制
3. 长时间网络中断: 全量复制
- 部分(增量)复制三要素
1. 服务器运行的ID(run id)
2. 主服务器的复制积压缓冲区(backlog)
3. 主从服务器复制的偏移量(offset)
- 服务器运行ID:
概念: 服务器运行ID是每个Redis实列运行的唯一身份标识码、每次重启后服务器ID都会改变。
组成:运行ID是由40位字符组成、是一个随机的十六进制的字符串。
作用:用于服务实列之间通信时的身份标识。
如果两次操作均对同一台服务器上的实列进行操作,则必须携带其运行runid
实现方式: 每台服务实列在启动时自动生成运行id、Master在首次连接上Slave时会将自己的runid发送给Slave、Slave进行保存。可以通过 info server 命令来查看节点的runid。
- 复制缓冲区:
复制缓冲区又称为复制积压缓冲区、是一个先进先出的队列(backlog)。用于存储服务器执行过的命令、每次传播命令时主服务器都会将传播的命令记录下来并存储在复制缓冲区、并记录当前命令在缓冲区中的偏移量范围。
复制缓冲区默认存储空间的大小为1M
当入队列元素的超过队列的长度会将队首的元素弹出并丢弃、新元素加入队列。
作用: 保存Master接收到的所有执行(仅是影响数据状态变化的的指令set、select)的指令
数据来源: Master 接收到客户端的指令时除了执行该指令还会将该指令保存到缓冲区。
看图说话
偏移量:
概念: 就是一个数字,用来描述缓冲区命令字节的位置。
分类:
Master偏移量:记录发送给Slave字节命令的偏移量(多个)
Slave偏移量:记录Slave接收到字节命令的偏移量(一个)
作用:
同步信息用、当Master和Slave断线重连后对比差异,进行数据同步。
数据来源:
Master: 发送一次记录一次
Slave: 接收一次记录一次
三、增量复制和全量复制的时机
经过上面的介绍基本明白了什么是全量复制什么是增量复制以及其原理。
现在我们来总结下什么时候进行增量复制什么时候进行全量复制。
当Master 收到PSYNC命令时会进行以下操作。
1、首先Master会判断Slave传过来的run id是否是自己的run id、确保Slave之前确实是和自己同步的、以免发生Slave拿到错误的数据(如Master重启过,会造成数据不一致)。
2、判断从数据库发送的偏移量是否在缓冲队列中如果在则发生增量同步、Master会将缓冲队列中的命令发送给Slave。
如果此次重连不符合上述条件就会发生全量复制。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。