Redis 集群之主从复制(八)

1. 主从复制简介

1.1 单击Redis的风险与问题

单机即在一台机器上部署一个redis节点,主要会存在以下问题:

  • 机器故障
  • 现象:硬盘故障、系统崩溃
  • 本质:数据丢失,很可能对业务造成灾难性打击
  • 结论:基本上会放弃使用Redis
  • 容量瓶颈
  • 现象:内存不足,从16G升级到64G,从64G升级到128G,无限升级内存
  • 本质:穷或硬件条件跟不上
  • 结论:放弃使用Redis

为了避免单点Redis服务器故障,准备多台服务器,互相连通。将数据复制多个副本保存在不同的服 务器上,连接在一起,并保证数据是同步的。即使有其中一台服务器宕机,其他服务器依然可以继续提供服务,实现Redis的高可用,同时实现数据冗余备份。

1.2 多台服务器连接方案

在这里插入图片描述

  • 提供数据方:master,也可以叫做主服务器、主节点、主库
  • 接收数据防:slave,从服务器、从节点、从库
  • 需要解决的问题:数据同步
  • 核心工作:master的数据复制到slave中

1.3什么是主从复制

主从复制,是指将一台Redis服务器的数据,即时、有效的复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

  • 特征

一个master可以拥有多个slave,一个slave只对应一个master

  • 职责
  • master:
    写数据
    执行写操作时,将出现变化的数据自动同步到slave
    读数据(可忽略)
  • slave:
    读数据
    写数据(禁止)

1.3 主从复制的作用

  • 读写分离:master写、slave读,提高服务器的读写负载能力
  • 负载均衡:基于主从结构,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数 量,通过多个从节点分担数据读取负载,大大提高Redis服务器并发量与数据吞吐量
  • 故障恢复:当master出现问题时(机器故障),因为数据有备份,方便恢复
  • 数据备份:实现数据热备份,是持久化之外的一种数据备份方式
  • 高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案

2. 主从复制的使用

2.1 建立主从结构

需要注意,主从复制的开启,完全是在从节点发起的,不需要我们在主节点做任何事情。
从节点开启主从复制,有3种方式:

  • 客户端发送命令
slaveof <masterip> <masterport>

注意是从服务器的客户端发送命令

  • 启动服务器参数
redis-server --slaveof <masterip> <masterport> 

注意是在从服务器的启动命令(redis-server)后加--slaveof <masterip> <masterport>

  • 服务器配置
 slaveof <masterip> <masterport> 

注意是在从服务器的配置文件中加入此配置

工作中一般使用的是第三种方式,开启了主从复制之后,可以在服务器(包括主从)开启的页面中看到相关信息,并且主服务器会自动将数据同步到从服务器中,不需要你做任何操作。

2.2 断开主从

通过slaveof 命令建立主从复制关系以后,可以通过从服务器客户端执行slaveof no one命令断开。需要注意的是,从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。

3. 主从复制的工作流程

主从复制过程大致可以分为3个阶段

  • 建立连接阶段
  • 数据同步阶段
  • 命令传播阶段

在这里插入图片描述

3.1 建立连接阶段

建立slave到master的连接,使master能够识别slave,并保存slave端口号

  • 工作流程

slave 工作流程

  • 步骤1:设置master的地址和端口,保存master信息
  • 步骤2:建立socket连接
  • 步骤3:发送ping命令(定时器任务)
  • 步骤4:身份验证
  • 步骤5:发送slave端口信息
    如图,左边是master做的事情,右边是slave做的事情
    在这里插入图片描述

最终达到的状态

  • slave:保存master的地址与端口号
  • master:保存slave的端口号
  • 总体:之间创建了socket连接

3.2 数据同步阶段

  • 在slave初次连接后,复制master中的所有数据到slave,全量复制

  • 将slave的数据库状态更新成master当前的数据库状态(全量复制过程中,新的数据变化),部分复制

  • 工作流程

slave 工作流程

  • 步骤1:请求同步数据
  • 步骤2:创建RDB同步数据
  • 步骤3:恢复RDB同步数据
  • 步骤4:请求部分同步数据
  • 步骤5:恢复部分同步数据
    至此,数据同步工作完成
    在这里插入图片描述

最终达到的状态

  • salve:具有master端全部数据,包含RDB过程接收的数据
  • master:保存slave当前数据同步的位置
  • 总体:之间完成了数据克隆

注意

  • 在数据同步阶段之前,从节点是主节点的客户端,主节点不是从节点的客户端;而到了这一阶段及以后,主从节点互为客户端。原因在于:在此之前,主节点只需要响应从节点的请求即可,不需要主动发请求,而在数据同步阶段和后面的命令传播阶段,主节点需要主动向从节点发送请求(如推送缓冲区中的写命令),才能完成复制。
  • 如果网络中断时间过长,导致主节点没有能够完整地保存中断期间执行的写命令(缓冲区中的指令被挤出去了),则无法进行部分复制,仍使用全量复制。
  • 复制缓冲区大小设定不合理,会导致数据溢出。如进行全量复制周期太长,进行部分复制时发现数据已 经存在丢失的情况,必须进行第二次全量复制,致使slave陷入死循环状态。 可以使用 repl-backlog-size 属性配置缓冲区大小
  • 主节点通过网络将RDB文件发送给从节点,对主从节点的带宽都会带来很大的消耗
  • 主节点通过bgsave命令fork子进程进行RDB持久化,该过程是非常消耗CPU、内存(页表复制)、硬盘IO的
  • 从节点首先清除自己的旧数据,然后执行RDB文件恢复数据

3.3 命令传播阶段

数据同步阶段完成后,主从节点进入命令传播阶段;在这个阶段,主节点将自己执行的写命令发送给从节点,从节点接收命令并执行,从而实时的保证主从节点数据的一致性(通过心跳机制实现)。
需要注意的是,命令传播是异步的过程,即主节点发送写命令后并不会等待从节点的回复;因此实际上主从节点之间很难保持实时的一致性,延迟在所难免。数据不一致的程度,与主从节点之间的网络状况、主节点写命令的执行频率、以及主节点中的repl-disable-tcp-nodelay配置等有关。

  • 命令传播阶段出现断网现象
  • 网络闪断闪连 ——忽略
  • 短时间网络中断 ——部分复制
  • 长时间网络中断 ——全量复制

3.4 部分复制的核心要素

部分复制除了用于同步阶段外,还用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。需要注意的是,如果网络中断时间过长,导致主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制。部分复制的实现,依赖于下面三个重要的概念:

  • 服务器运行ID(runid)
  • 概念:服务器运行ID是每一台服务器每次运行的身份识别码,一台服务器多次运行可以生成多个运行id
  • 组成:运行id由40位字符组成,是一个随机的十六进制字符 例如fdc9ff13b9bbaab28db42b3d50f852bb5e3fcdce
  • 作用:运行id被用于在服务器间进行传输,识别身份 ,如果想两次操作均对同一台服务器进行,必须每次操作携带对应的运行id,用于对方识别
  • 实现方式:运行id在每台服务器启动时自动生成的,master在首次连接slave时,会将自己的运行ID发 送给slave,slave保存此ID,通过info Server命令,可以查看节点的runid
  • 复制缓冲区
    在命令传播阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积压缓冲区,作为写命令的备份
  • 概念:复制缓冲区,又名复制积压缓冲区,是一个先进先出(FIFO)的队列,用于存储服务器执行过的命令,每次传播命令,master都会将传播的命令记录下来,并存储在复制缓冲区 。 复制缓冲区默认数据存储空间大小是1M,由于存储空间大小是固定的,当入队元素的数量大于队 列长度时,最先入队的元素会被弹出,而新元素会被放入队列
  • 由来:每台服务器启动时,如果开启有AOF或被连接成为master节点,即创建复制缓冲区
  • 作用:用于保存master收到的所有指令(仅影响数据变更的指令,例如set,select)
  • 数据来源:当master接收到主客户端的指令时,除了将指令执行,会将该指令存储到缓冲区中
  • 复制缓冲区工作原理

组成

  • 偏移量
  • 字节值

工作原理

  • 通过offset区分不同的slave当前数据传播的差异
  • master记录已发送的信息对应的offset
  • slave记录已接收的信息对应的offset
  • 主节点根据offset和缓冲区大小决定能否执行部分复制,如果offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制;如果offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制。也就是判断指令是否被挤出去,如果被挤出,就全量复制,没有被挤出去,就部分复制
    在这里插入图片描述
  • 偏移量
  • 概念:一个数字,描述复制缓冲区中的指令字节位置
  • 分类:
    master复制偏移量:记录发送给所有slave的指令字节对应的位置(多个)
    slave复制偏移量:记录slave接收master发送过来的指令字节对应的位置(一个)
  • 数据来源
    master端:发送一次记录一次
    slave端:接收一次记录一次
  • 作用
    同步信息,比对master与slave的差异,当slave断线后,恢复数据使用

3.4 数据同步和命令传播阶段详细工作流程

在这里插入图片描述

3.5 心跳机制

  • 在命令传播阶段,master与slave间需要进行信息交换,使用心跳机制进行维护,实现双方连接保持在线

master 心跳
指令:ping
周期:由repl-ping-slave-period 决定,默认10秒
作用:判断slave 是否在线
查询:info replication 获取slave最后一次连接时间间隔,lag 项维持在0或1视为正常

slave 心跳

  • 指令:replconf ack offset
  • 周期:1秒
  • 作用:汇报slave自己的复制偏移量,获取最新的数据变更指令。判断master是否在线
  • 心跳阶段注意事项
  • 当slave多数掉线,或延迟过高时,master为保障数据稳定性,将拒绝所有信息同步操作,使用下面两个参数进行配置
    min-slaves-to-write 2 主从复制的最小slave数
    min-slaves-max-lag 8 主从复制所有slave的最大延迟
    slave数量少于2个,或者所有slave的延迟都大于等于8秒时,强制关闭master写功能,停止数据同步
    slave数量和延迟由slave发送REPLCONF ACK命令做确认

3.6 完整流程

在这里插入图片描述

4. 主从复制常见问题

  • 频繁的全量复制

伴随着系统的运行,master的数据量会越来越大,一旦master重启,runid将发生变化,会导致全部slave的 全量复制操作

  • 内部优化调整方案
  1. master内部创建master_replid变量,使用runid相同的策略生成,长度41位,并发送给所有slave
  2. 在master关闭时执行命令 shutdown save,进行RDB持久化,将runid与offset保存到RDB文件中 ,通过redis-check-rdb命令可以查看该信息
  3. master重启后,将RDB文件中保存的repl-id与repl-offset加载到内存中 ,通过info命令可以查看该信息
  • 作用
    本机上次runid,重启后恢复该值,使所有slave认为还是之前的master
  • 频繁的全量复制2
  • 问题现象:网络环境不佳,出现网络中断,slave不提供服务
  • 问题原因:复制缓冲区过小,断网后slave的offset越界,触发全量复制
  • 最终结果:slave反复进行全量复制
  • 解决方案
    修改复制缓冲区大小,repl-backlog-size
  • 建议设置如下:
  1. 测算从master到slave的重连平均时长second
  2. 获取master平均每秒产生写命令数据总量write_size_per_second
  3. 最优复制缓冲区空间 = 2 * second * write_size_per_second
  • 频繁的网络中断
  • 问题现象: master的CPU占用过高 或 slave频繁断开连接
  • 问题原因
    slave每1秒发送REPLCONF ACK命令到master
    当slave接到了慢查询时(keys * ,hgetall等),会大量占用CPU性能
    master每1秒调用复制定时函数replicationCron(),比对slave发现长时间没有进行响应
  • 最终结果
    master各种资源(输出缓冲区、带宽、连接等)被严重占用
  • 解决方案
    通过设置合理的超时时间(repl-timeout,该参数定义了超时时间的阈值(默认60秒),超过该值,释放slave ),确认是否释放slave
  • 频繁的网络中断2
  • 问题现象:slave与master连接断开
  • 问题原因
    master发送ping指令频度较低
    master设定超时时间较短
    ping指令在网络中存在丢包
  • 解决方案
    提高ping指令发送的频度 repl-ping-slave-period,超时时间repl-time的时间至少是ping指令频度的5到10倍,否则slave很容易判定超时
  • 数据不一致
  • 问题现象:多个slave获取相同数据不同步
  • 问题原因: 网络信息不同步,数据发送有延迟
  • 解决方案
    优化主从间的网络环境,通常放置在同一个机房部署,如使用阿里云等云服务器时要注意此现象
    监控主从节点延迟(通过offset)判断,如果slave延迟过大,暂时屏蔽程序对该slave的数据访问
    slave-serve-stale-data yes|no 开启后仅响应info、slaveof等少数命令(慎用,除非对数据一致性要求很高)

参考:

猜你喜欢

转载自blog.csdn.net/weixin_43691723/article/details/106260493