📕技术箴言
当心中有更高的山峰去攀登,就不会在意脚下的泥沼。
📕前提概要
Redis高可用的方案包括:持久化、主从复制(及读写分离)、哨兵和集群(Cluster)。
📕📕 持久化:
侧重解决的是Redis数据的单机备份问题(从内存到硬盘的备份),数据可用性以及可靠性。
📕📕 主从复制
侧重解决数据的多机热备,以及从实例角度进行解决提高了高可用(故障切换),主从复制还可以实现负载均衡(高性能)。
📕📕 哨兵
侧重于服务实例角度,自动进行监控和切换,进行解决实例之间提高了高可用(故障切换)
📕📕 集群
侧重于服务实例和数据角度,进行数据容灾以及高可用的能力,此外可以扩展单节点redis的数据存储上限。
📕 内容提要
本片文章主要将详细介绍Redis主从复制的内容包括:如何使用主从复制、主从复制的原理(重点是全量复制和部分复制、以及心跳机制)、实际应用中需要注意的问题(如数据不一致问题、复制超时问题、复制缓冲区溢出问题)、主从复制相关的配置(重点是repl-timeout、client-output-buffer-limit slave)等。
📕主从复制的概述
总体过程
-
主节点负责写数据,从节点负责读数据。
-
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。
-
前者称为主节点(master),后者称为从节点(slave);
-
数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
📕主从复制的作用
-
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式,数据可以保证可用性和一致性。
-
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
-
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
-
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
📕主从复制的拓扑
📕📕一主一从
- 主节点故障转移从节点,当主节点的“写”命令并发高且需要持久化,可以只在从节点开启AOF(主节点不需要),这样即保证了数据的安全性,也避免AOF持久化对主节点的影响
📕📕一主多从
- 针对“读”较多的场景,“读”由多个从节点来分担,但节点越多,主节点同步到多节点的次数也越多,影响带宽,也加重主节点的负担
📕📕 树状主从:
- 一主多从的缺点(主节点推送次数多压力大)可用些方案解决,主节点只推送一次数据到从节点B,再由从节点B推送到C,减轻主节点推送的压力。
📕 主从复制的原理
了解redis复制原理对日后运维有很大帮助,包括如何规划节点,如何处理节点故障,redis复制过程可分为三个阶段:
- 复制初始化阶段
- 数据同步阶段
- 命令传播阶段
📕📕 复制初始化阶段
主从复制主要实现的一个流程如上图:
1. 当执行完slaveof/replica masterip port命令时候,从库根据指明的master节点ip和port向主库发起socket连接,主库收到socket连接之后将连接信息保存,此时连接建立,从服务器保存主服务器的配置信息,保存之后待从服务器内部的定时器执行时,就会触发复制的流程。
注意:replicaof 是新版本的命令,旧版本是 slaveof 命令,如果你使用的是 Redis 5.0.0 之前的版本,那么请使用 SLAVEOF 命令代替本章中的 REPLICAOF 命令,并使用 slaveof 配置选项代替本章中的 replicaof 配置选项
2. 从服务器首先会与主服务器建立一个socket套字节连接,用作主从通信使用。后面主服务器发送数据给从服务器也是通过该套字节进行。
3. socket套字节连接成功之后,接着发送鉴权ping命令,正常的情况下,主服务器会发送对应pong的响应。ping命令的作用是为了,保证socket套字节是否可以用,同时也是为了验证主服务器是否接受操作命令,否则可能出现超时或者主库此时在处理其他任务阻塞那么此时从库将断开socket连接,然后进行重试
4. 如果主库连接设置了密码,则从库需要设置masterauth参数,此时从库会发送auth命令,命令格式为“auth + 密码”进行密码验证,其中密码为masterauth参数配置的密码,需要注意的是如果主库设置了密码验证,从库未配置masterauth参数则报错,socket连接断开。当身份验证完成以后,从节点发送自己的监听端口,主库保存其端口信息,此时进入下一个阶段:数据同步阶段
5. 可以开始复制数据了。主服务器此时会进行全量复制,将主服务的数据全部发给从服务器,从服务器保存主服务器发送的数据。
6.接下来就是持续复制操作。主服务器会进行异步复制,一边将写的数据写入自身,同时会将新的写命令发送给从服务器。
📕📕 数据同步阶段
-
主库和从库都确认对方信息以后,便可开始数据同步,此时从库向主库发送psync命令(需要注意的是redis4.0版本对2.8版本的psync做了优化,后续会进行说明),
-
主库收到该命令后判断是进行增量复制还是全量复制,然后根据策略进行数据的同步,当主库有新的写操作时候,此时进入复制第三阶段:命令传播阶段。
📕📕 命令传播阶段
-
当数据同步完成以后,在此后的时间里主从维护着心跳检查来确认对方是否在线,每隔一段时间(默认10秒,通过repl-ping-replica-period/repl-ping-slave-period参数指定)主节点向从节点发送PING命令判断从节点是否在线。
-
从节点每秒1次向主节点发送REPLCONF ACK命令,命令格式为:REPLCONF ACK {offset},其中offset指从节点保存的复制偏移量。
- 作用一是汇报自己复制偏移量,主节点会对比复制偏移量向从节点发送未同步的命令。
- 作用二在于判断主节点是否在线,从库接送命令并执行,最终实现与主库数据相同。
📕📕 主从乐观复制机制
Redis采用量乐观复制策略,容忍在一定时间内主从数据内容是不同的,但是两者的数据最终会同步。
📕📕 主从复制实现策略
Redis主从复制主要分为三种弄策略方式,不同的策略方式都是针对不同的场景下进行使用。三种场景方式分别如下:
📕📕📕 全量复制
全量复制用在主从复制刚建立时或者从切主服务器时,从服务器没有主服务器的数据,主服务器会将自身的数据通过rdb文件方式发送给从服务器,从服务器会清空自身数据,接着将主服务器发送的数据加载到自身中。
1. 从服务器->主服务器: 1.psync ? -1
2. 主服务器->从服务器: 2.fullsync runid offset
3. 从服务器: 保存 runid offset
4. 主服务器: 执行bgsave生成rdb
5. 主服务器->从服务器: 发送rdb
6. 从服务器: 清空自身老数据
7. 从服务器: 加载主服务器数据
📕📕📕 部分复制
部分复制用在一些异常情况下,例如主从延迟、从服务宕机之后重新启动接收主服务器发送的部分数据。
部分复制的实现主要依赖于复制缓存区、主服务的runid、主从服务器各自复制偏移量(offset)。
📕📕📕📕 复制缓存区**
repl_backlog_size:保存在主节点上的一个固定长度的先进先出队列,默认大小是1MB。
-
主服务在接收写命令时,会将命令写入缓存区,以便从服务器在异常情况下,减少数据的丢失。
-
当从服务器正常连接之后,主服务器会将缓存区内的数据发送给从服务器。这里的缓存区是一个长队列。
-
主节点发送数据给从节点过程中,主节点还会进行一些写操作,这时候的数据存储在复制缓冲区中。从节点同步主节点数据完成后,主节点将缓冲区的数据继续发送给从节点,用于部分复制。
-
主节点响应写命令时,不但会把写命令发送给从节点,还会写入复制积压缓冲区,用于复制命令丢失的数据补救。
📕📕📕📕 主服务器runid
- 主服务器会在每次服务启动之后,会生成一个唯一的ID,作为自身标识。从服务器会将该标识保存起来,发送部分复制命令时,会使用该runid。
psync runid offset
📕📕📕📕 主从复制各自偏移量:
主从服务在建立复制之后,都会有自身的偏移量offset。
-
主节点在每次进行了写命令之后,也会增加自身的偏移量(offset=offset+命令的字节长度)。这里的偏移量是通过命令的字节长度累加计算。
-
从节点会每秒钟发送自身复制的偏移量给主节点,主节点在发送写命令之后,从节点也会增加自身的复制偏移量(也会增加自己的offset)。
主节点同时保存自己的offset和从节点的offset,通过对比offset来判断主从节点数据是否一致。
📕📕📕 异步复制
异步复制是针对主从建立复制关系之后,主从服务器持续保持复制关系。
📕📕 场景问题
📕📕📕 数据安全
- 从服务器只读
replica-read-only yes
- 从服务器连接密码
masterauth
📕📕📕 数据延迟。
默认的情况下主节点存在新数据不会立即发送给从服务器,如果开启,则会理解延迟发送给从服务器。默认的时间间隔与Linux内核定义有关。
- 复制延迟
repl-disable-tcp-nodelay yes
📕📕📕 主从节点连接状态。
主从节点一旦建立连接之后,会定时模拟成对方的客户端,检测对方的服务状态。主节点可以通过设置repl-ping-replica-period/repl-ping-slave-period配置参数进行设置。默认的频率是10s。
从节点咋执行**replconf ack {offsetid}**时,也会将自身的复制偏移量发送给主服务器,主服务根据偏移量进行判断数据延迟。存在数据延迟就会从复制积压缓冲区的数据汇中,将对应的数据补发给从节点。
。