redis进阶---redis集群(一):主从复制

2020-06-20

*引入:

又是一个美好的周末,今天更新一下redis集群相关理论基础。对于一个不爱学理论的我来说,感觉好像很难得。好了开整。在互联网中有互联网三大架构:高性能、高并发、高可用(一年时间中服务器宕机的百分比,业界追求目标99.999%,也就是一年中宕机时间低于315秒)。而对于redis如何做到三高呢?

之前写道的redis一直以单机的形式出现,但是单机的redis会存在许多的问题,例如:硬盘司死机、系统崩溃,造成数据丢失等等,或者是内存不足,不停升级(穷,资源跟不上)等等问题。那应该怎么做呢?

为了避免单点redis服务器的故障造成的各种灾难性打击,准备多台服务器,相互连通,将数据赋值到多个副本保存在不同的服务器上,连接在一起,然后保证数据同步,那么哪怕1/2台服务器宕机了,依然可以继续提供服务,实现redis的高可用,同时实现数据的冗余备份。这就出现了redis的主从复制。



一、主从复制简介:

主从复制:以数据同步为核心问题出发,将主服务的数据及时、有效的复制到从服务器上。

主从服务器:

服务器连接例子.png

主:

名称:主服务器、主节点、主库、主客户端
职责:写数据、执行写数据的同时将数据同步到从服务器上,读数据(可忽略)
从:
名称:从服务器、从节点、从库、从客户端
职责:禁止写数据、只做读数据

过程:

  1. 建立连接
  2. 同步数据(在数据上保持一直)
  3. 命令传播(反复同步的过程)

作用:
读写分离: 主服务器负责读、从而提高服务器的读写负载的能力
负载均衡:基于主从结构、配合读写分离,由于从服务器分担主服务器的负载,并且根据需求变化、改变从服务器的数量,通过多个节点分担数据读取负载,大大提高redis服务器得并发量与数据吞吐量。
故障恢复:主服务器出现问题时候从服务器提供服务,从而实现快速得故障恢复
数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式。
高可用的基石:基于主从复制,构建哨兵模式与集群,实现redis的高可用方案。

主从服务器串联.png



二、过程介绍

(一)、建立连接

1.主要步骤:

  • 设置主服务器的地址和端口号,保存master的信息
  • 建立socker连接(用户后期数据发送通道)
  • 发送ping指令(定时发送,检测master是否还在)
  • 身份验证
  • 发送slave端口信息

image.png
图解说明:
从服务器发送指令:slaveof ip port 。主服务器接收命令后做出相应,然后从服务器保存主服务器的ip与端口号。
此时的从服务器知道主服务器存在,但以后要怎么才能和它进行数据交互呢?于是从服务器开启socket,用于以后与master进行RDB文件与相关的数据的传输。之后从服务器开始进行周期性的Ping。主服务器以PANG进行回应。如果设置有密码的的话还需要进行auth password发送,然后主服务器进行权限验证。最后从服务器发送replconflistening-port给主服务器。主服务器保存slave的端口号。

具体案例:
方式一:启动后建立连接:slaveof 127.0.0.1 6384
方式二:启动时建立连接:redis-server 6384.conf --slaveof 127.0.0.1 8384
方式三:配置文件:slaveof 127.0.0.1 6379
断开连接命令: 从服务器发送 slaveof no one

命令启动:
( 看不清图片自己放大看,或者下载下来)
主从服务器.png

直接启动
直接启动.png

  • 相关说明:
    • master:
      1、 如果主服务器数据量巨大, 数据同步同步阶段应该避开流量高峰期,避免造成主服务器阻塞,影响业务执行。
      2、 如果缓冲区大小设定不合理,会导致数据溢出。
      如果进行全量复制的周期太长,进行部分复制时发现数据已经存在丢失的情况需要进行第二次全量复制,从而导致从服务器陷入死循环。(为什么会出现数据丢失呢?因为在进程权力复制时,主服务器会对接收的指令开辟一定空间的指令缓冲区,当指令过多时,缓冲区已经满了,就只能移除最初进来的指令)解决方案: 设置master的缓冲区大小:repl-backlog-size 1mb
      3、 master单机内存占用主机内存的比例不应过大,建议留有30-50%的内存用于执行bgsave命令和创建复制缓冲区
    • slave:
      1、 为了避免从服务器进行全量复制、部分复制时服务器响应阻塞或数据不同步,建议关闭此期间的对外服务
      slave-serve-stale-data yes|no
      2、 多个从服务器同时对主服务器请求数据同步,主服务器发送的RDB文件增多,会对带宽造成巨大的冲击,如果主服务器的带宽不足,要根据不同的业务需求错开峰值请求
      3、 从服务器过多时,将以调整拓扑结构,由一主多从结构变为树结构,中间结点既是master也是slave。(注意使用树状结构时,由于层级深度,会造成越深的slave与顶层的master间数据同步延迟较大,数据的一致性变差,使用应谨慎)

(二)、数据同步

  • 主要步骤:
    步骤1:请求同步数据
    步骤2:创建RDB同步数据
    步骤3:恢复RDB同步数据
    步骤4:请求部分同步数据
    步骤5:恢复部分同步数据
    完成!
    PS: 从服务器具有主服务器的全部数据,包含在生成RDB过程中接收的数据
    主服务器能够保存从服务器当前数据同步的位置
    image.png
  • 图解说明
    从服务器发送指令psync2给主服务器主服务器接收命令后执行bgsave命令、创建命令缓冲区(后文介绍),之后生成RDB文件,将RDB通过之间建立的socket发送给从服务器,从服务接收RDB文件后执行RDB恢复数据。至此全部复制结束,但是这个时候他们的数据就是一样的吗?万一在生成RDB的过程中有大量命令进来呢?这时候他们的数据就会造成不一致。所以还需要执行部分复制,从服务器等恢复结束后告诉主服务器,我恢复好了,主服务器就将缓冲区的指令发送给从服务器,从服务器接收后执行bgrewriteof恢复数据。

(三)、命令传播

  • 命令传播:当主服务器数据库被修改后,导致主从服务器数据库状态不一致,这时需要让主从数据同步到一致的状态,同步的动作称为命令传播。也就是主服务器将接收到的数据变更命令发送给从服务器,从服务器接收指令后执行。
  • 命令传播阶段的部分复制。
    背景:大家有没有设想过,当我们在命令传播阶段突然断网停电了怎么办呢???这时候我们就要分三种情况考虑了:
    • 网络闪断闪连,直接忽略
    • 网络短时间中断,启用部分复制
    • 长时间中断是全量复制

这时候我们需要注意部分复制的核心三要素

    • 服务器运行的id
    • 主服务器的复制积压缓冲区
    • 主服务器的复制偏移量

接下来我们详细说说这几个东西:

服务器运行id

  • 概念:服务器运行id是每一台服务器每一次运行的身份识别码,一台服务器多次运行后会产生多个id
  • 组成:塌事故体验40位16进制的随机字符组成
  • 作用:运行id被用于服务器间进行传输的身份识别(每次操作都需要携带对应的运行id用于识别)
  • 实现方式:运行id在每台服务器启动时生成,主服务器在每次连接从服务器时,都会将自己的运行id发送给从服务器,从服务器保存此ID。(可通过info server命令查看 节点的runid)

复制缓冲区

  • 背景:当主服务与从服务器进行收发时候会启动一个命令传播程序来完成这件事,但是在这个过程他断网了会怎么样呢?那对应的slave就会接收不到对应的命令。但是其他的几个slave并没有断网,因此他们还是能够接收到相应的命令。这时候出现了什么问题呢?就是几个slave之间的数据并不是一样的。这时候需要怎么办呢?就是命令在发送的过程中同时将命令加入复制缓冲区
  • 概念:复制缓冲区又名复制积压缓冲区是一个先进先出(FIFO)的队列,用于存储服务器执行过程的命令,每次传播命令,master都会将传播记录下来,并存储在复制缓冲区。
    组成字节值、偏移量
    作用:用于保存master接收到的所有指令(只是影响数据变更的指令,例如set、select等)
    工作原理:master与slave都同时记录offset对应的收发位置通过offset区分不同的slave当前数据传播的差异。
    image.png

图解说明:当master接收到一个指令后如标号1(set name test)它会将这个指令拆解开,拆解为标号2格式(类似AOF文件格式)
然后将其每个字节压入复制缓冲区,每个字节值对应一个偏移量。这时候即使发送过程中断电断网只需要记录其偏移量offset,然后进行恢复。

PS:

  • 复制缓冲区大小默认位1Mb,由于存储空间大小固定,当其入队元素满了以后还有元素入队,那么最先入队的元素就会被弹出。
  • 每台服务器在启动的时候如果有AOF或者是成为了master的一个节点都会创建复制缓冲区
  • 当master接收到主客户端的指令的时候,除了执行指令,还会将其指令保存到复制积压缓冲区。

复制偏移量
概念:用于描述复制缓冲区的指令的字节位置
分类:master复制偏移量与slave复制偏移量

  • master复制偏移量:记录发给slave对应指令字节的位置(多个)
  • slave复制偏移量:记录当前接收指令字节位置(一个)
    作用:同步信息,对比slave与master的差异,当slave断线后用于恢复数据使用

数据同步+命令传播阶段的工作流程:
image.png
图解:当slave第一次与master建立连接的时候由于不知道offset偏移量的位置,所以就发送psync2 ? -1给master,master接收到信息后执行bgsave然后生成RDB文件,并记录offset,随后发送 +FULLRESYNC runid offset。通过socket发送RDB文件给slave,slave收到 +FULLRESYNC 然后保存master的runid和offset,通过RDB恢复数据,现在全局复制结束,此时已经有offset了,然后他就发送命令psync2 runid offset给master,master收命令。判断runid是否匹配,判断offset是否在复制缓冲区中。接着这时候master判断runid或者offset有一个不匹配的话开始执行bgsave然后进行全局复制,如果他们都相同则校验通过,如果offset不同,则发送 +FULLRESYNC offset。通过socket发送缓冲区中的offset数据,然后slave收到 +CONTINUE 后 保存master的offset接收信息,执行bgrewriteaof恢复数据。



三、心跳机制

前面传播阶段不是要一致依靠着一个反复运行的机制来维护者,这个反复的机制就是心跳机制
什么是心跳机制呢?进入命令传播阶段,master与slave间进行信息交换,使用心跳机制进行维护,实现双方连接保持在线。

  • master心跳:
    指令:ping
    周期:由repl-ping-slave-period决定,默认10秒
    作用:判断slave是否在线
    查询:INFO replication获取slave最后一次连接时间间隔,lag项维持在0或1为正常
  • slave心跳
    指令:REPLCONF ACK [offset]
    周期:1s
    作用:
  • 汇报slave自己的复制偏移量、获取最新的数据变更指令
  • 判断master是否在线

安全性
当slave掉线过多,或者延迟较高,但是为了保证master的数据稳定性,我们可以通过设置参数:
min-slave-to-weite 3
min-slave-max-lag 10

当slave数量少于2个。或者所有的slave的延迟都大于10秒时,强制关闭master的写功能。停止数据同步
(slave数量与延迟都是由slave发送的**REPLCONF ACK **命令做确认)



四、主从复制常见问题

1、频繁的全量复制
问题一:随着master的数量越来越大,一旦master重启,ranid将会变化,从而引起全部slave的全量复制操作
内部优化方案

  • master内部创建master——replid遍历,使用runid相同的策略生成。长度41位,并发送给所有的slave
  • 在master关闭时执行命令 shutdown save进行RDB持久化,并将runid与offset保存到RDB中。
  • master重启后加载RDB文件,恢复数据。重启后,将RDB文件保存在repl-id与repl-offset加载到内存中
    作用:本机保存上次的runid,重启后恢复该值,让所有slave认为还是之前的master

问题二:网络环境不好没出现网络中断,slave不提供服务。使得复制缓冲区国小,断网后slave的offset月结,从而使slave反复进行全量复制

优化方案:修改缓冲区大小:repl-backlog-size(测算master到slave的重连平均时长或者在系统中master平均每秒产生写命令的总量write_size_per_second,最有缓冲区空间=2 x second x write_size_per_second)

2、频繁的网络中断
问题一:slave每秒发送的RELCONF ACK命令到master 或者slave进行慢查询(keys *,hgetall等)或者是master每秒调用复制定时函数replicationCron(),然后发现slave长时间没有相应。从而造成master各种资源(输出缓冲区、带宽等)被严重占用,造成master的CPU使用过高或者slave频繁断开连接
优化方案:通过设置合理的超时时间,确认是否释放slave。
repl-timeout 默认大小60秒。超时则释放slave。

问题二:master发送ping指令频度较低或者设定超时间较短,以及ping指令在网络中丢包,造成slave与master连接断开
解决方案:提高ping指令发送的频度。设置:**repl-ping-slave-period **(超时时间repl-timeout的时间至少是ping指令频度的5-10倍。否则slave容易超时)

3、数据不一致
问题:由于网络信息不同步,数据发送有延迟,从而造成多个slave获取相同数据时出现不同步
解决方案

  • 优化主从之间的换了环境,尽量在同一个机房部署
  • 减重主节点延迟(通过offset)判断,如果slave延迟过大,屏蔽该slave的数据访问。设置:slave-server-stale-data yes|no 开启后仅相应info、slaveof等少数命令。

标题:redis进阶---redis集群(一):主从复制
作者:sirwsl
地址:https://www.wslhome.top/articles/2020/06/20/1592648158747.html