第六章 主从复制

目录
一、简介
二、作用
三、工作流程
四、常见问题

一、简介

主从复制(主服务器的数据 -----> 从服务器"读")的"三高"

image-20200830184853031.png

单台redis服务器"高可用"?

  1. 问题一:硬盘,系统故障,可能对数据造成灾难性打击
  2. 问题二:内存不足,升级加硬件,但是加硬件总有上限,接口不足
  3. 总结:单台Redis服务器不可考,为了避免单点的Redis服务器故障,准备多台服务器,互相连通。数据复制到多个副本保存,并保证数据是同步的(一台挂了,其他正常),从而实现Redis的高可用,也实现的冗余备份

多台计算机的连接方案

image-20200830185907349.png

二、作用

如何redis集群挂了,怎么办?

  1. 从服务器(读)挂了----问题不大,还有很多
  2. 主服务器(写)挂了----指定一台slave(从)变成master(写)
  3. 如果master负载压力过大-----让其中一台slave变成master并且扩展多几台slave连接在master下面

主从复制的作用

  1. 读写分离:master写,slave读,提高服务器的读写负载能力
  2. 负载均衡:有了主从结构和读写分离的配合,slave分担master的负载,可根据需求改变slave和master的数量,通过从多个从服务器中读取数据,大大地提高了Redis服务器的并发量和吞吐量
  3. 故障恢复:master出现问题,由slave提供服务,实现快速的故障恢复
  4. 数据冗余备份:实现数据的热备份,是数据持久化的一种方式
  5. 高可用基石:基于主从复制,构建哨兵模式和集群,实现Redis的高可用

三、工作流程

主从复制的三个阶段

连接(主 < ---- 从)
同步(主 ----> 从)--(全量复制+部分复制)
命令的实时同步(主 --> 从)--(部分复制)

image-20200830192000578.png

阶段一:建立连接

建立连接原理图

image-20200830192854227.png

操作(6379主----------6380从),slave连接指令给master的三种方式

  • 直接在slave客户端输入:slaveof 127.0.0.1 6379

  • 在启动slave服务器的时候:

    redis-cli 配置文件路径/redis-6380.conf --slaveof 127.0.0.1 6379

  • 在redis-6380.conf配置文件加入

    --slaveof 127.0.0.1 6379

  • 连接成功的info数据


    image-20200830194939082.png
  • 连接的三种方式和slave与master断开(slave发送命令,因为master还有其他slave连着)


    image-20200830195217433.png
  • 授权访问(slave -- 发送password---> master)


    image-20200830195604812.png

阶段二:数据同步阶段

数据同步原理图

redis2.8 之后使用了PSYNC命令,4.0出现了PSYNC2(Partial resynchronization)
主节点(master)在处理完写入命令后,会把命令的字节长度做累加记录,统计信息会在info replication 指令中的master_repl_offset指标中

image-20200830214255433.png

全量复制:从节点请求发送同步指令之前,主节点中的所有数据都发送给从节点

1.Redis 内部会发出一个同步Psync ? -1 命令

2.主机会向从机发送 runid (redis-cli info server)和 offset,因为 slave 并没有对应的 offset,所以是全量复制

3.从机slave会保存主机master的基本信息 save masterInfo

4.主节点收到全量复制的命令后,执行 bgsave(异步执行),在后台生成 RDB 文件(快照),并使用一个缓冲区(称为复制缓冲区)记录从现在开始执行的所有命令

5.主机 发送 RDB 文件给从机(刷新旧的数据,从节点在载入主节点的数据之前要先将老数据清除)

6.发送缓冲区数据

7.加载 RDB 文件将数据库状态更新至主节点执行 bgsave 之前的数据库状态和缓冲区数据的加载

全量复制开销:
1.bgsave 时间
2.RDB 文件网络传输时间
3.从节点清空数据的时间
4.从节点加载 RDB 的时间

部分复制(增量复制):RDB过程中的指令

从节点开始接收RDB快照到接收完成期间,主节点仍然响应读写命令,因此主节点会把这期间写命令数据保存在复制客户端缓冲区内,当从节点加载完RDB文件后,主节点再把缓冲区内的数据发送个从节点,保证主从之间数据一致性。

如果主节点创建和传输RDB的时间过长,高流量写入容易造成主节点复制客户端缓冲区溢出。默认配置如下所示,如果60秒内缓冲区消耗持续大于64MB或者直接超过256MB时,主节点将直接关闭复制客户端连接,造成全量同步失败

redis.conf 配置
client-output-buffer-limit replica 256mb 64mb 60

从节点将offset发送给主节点后,主节点根据offset和缓冲区大小决定能否执行部分复制

  • offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制;
  • offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤压)或者是新增的从服务器,则执行全量复制

master注意事项

  • master数据量大,数据同步应该避开高峰期,凌晨3-4点,否则影响正常的业务

  • 复制缓冲区设定不合理(太小),会导致数据溢出,如果全量复制的周期太长,进行部分复制发现数据以及存在丢失(被新数据挤走了,队列),必须进行第二次全量复制

    导致slave陷入了死循环,不断的清除数据,master不断的生成RDB

  • conf文件可配置复制缓冲区大小,默认1MB

    Repl-backing-size 1mb

  • master单击的内存占物理内存比例不能过大(最好50-70%),留下的给bgsave和创建复制缓冲区

slave注意事项

  • slave为避免在全量复制和部分复制期间服务器可能阻塞,建议关掉对外服务

    slave-serve-stale-data yes | no
    当主服务器挂了,是否提供过期数据
    slave-read-only yes
    开启只读服务

  • 多个slave同时对master请求同步,master的RDB文件增多,网络带宽造成冲击,如果master带宽不足,则需要错峰同步slave

  • slave过多时候,需要调整拓扑结构,一主多从 ----> 树状结构,导致深度越高的slave与顶层的master数据同步延迟大,数据一致性变差,需要接受数据的延迟

阶段三:命令传播阶段(反复同步---master被写数据)

image-20200830225645359.png

部分复制(增量复制)

部分复制主要是Redis针对全量复制的过高开销做出的一种优化措施,使用psync {runId}{offset}命令实现。当从节点(slave)正在复制主节点(master)时,如果出现网络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,主节点的复制积压缓冲区内存这部分数据则直接发送给从节点,这样就可以保持主从节点复制的一致性。补发的这部分数据一般远远小于全量数据.
1.如果网络抖动(连接断开 connection lost),主机master 还是会向replbackbuffer(复制缓冲区)发送数据,主节点内部存在的复制积压缓冲区,依然可以保存最近一段时间的写命令数据
2.从机slave 会继续尝试连接主机,把自己当前 runid 和偏移量传输给主机 master,并且执行 pysnc 命令同步
3.如果 master 发现你的偏移量是在缓冲区的范围内,就会返回 continue 命令
4.同步了 offset 的部分数据,所以部分复制的基础就是偏移量 offset。

运行id(run id)
定义:每一台Redis服务器的身份证识别码,每次运行都不一样,由40位字符组成(16进制)
作用:用于对方身份识别
实现方式:服务器启动自动生成,master首次连接slave,会将自己的run id发送给slave,slave会保存次ID,info server命令可查看run id

主服务器的复制积压缓冲区

  • 是一个保存在主节点上FIFO的固定长度队列,默认为1MB,主节点master连接从节点slave时或者开启了AOF(everysec)被创建,这时主节点(master)响应写命令,不但会把命令发送到从节点,还会写入到复制缓冲区
  • master接收到主客户端的指令,不仅会执行,还会将指令存储在缓冲区中
  • 在命令传播阶段过程,主节点将写命令发送给从节点(部分复制),还会发送一份备份给复制缓冲区。
  • 同时,复制缓冲区还存储了每个字节对应的复制偏移量(offset),由于复制积压缓冲区定长且先进先出,保存的是主节点的写命令(仅影响数据变更的指令set,select),所以时间较早的写命令会被挤出缓冲

复制积压缓冲区内部工作原理

image-20200831062735097.png

数据同步+命令传播阶段工作流程

image-20200831071407805.png

命令传播阶段的心跳机制
命令传播阶段master和slave需要进行信息交换,需要使用心跳机制维护,确认双方连接在线
master心跳(判断slave是否在线)

  • 通过ping指令
  • 周期:默认10秒,由repl-ping-slave-period决定
  • 查询:info replication 获取最后一次连接slave的时间间隔(lag == 0 || lag == 1)

slave心跳(判断master是否在线)

  • 通过REPLCONF ACK {offset}指令
  • 周期:默认1秒
  • 作用:汇报slave自己的复制偏移量,获取最新的变更指令

由于主从服务器的树状结构,树的深度影响延迟,slave延迟过高而掉线,如何优化?

  • 拒绝所有的对从服务器写同步操作,(都挂了,写操作已经没意义了 )
  • Redis的min-slaves-to-write 3和min-slaves-max-lag 10两个选项可以防止主服务器在不安全的情况下执行写命令
  • 从服务器的数量少于3个,或者三个从服务器的延迟(lag)值都大于或等于10秒时,主服务器将拒绝执行写命令
  • 数量和延迟是从slave服务器REPLCONF ACK确认时发出的

主从复制的三个阶段(全)

image-20200831074448816.png

四、常见问题

问题一:频繁的全量复制

频繁的全量复制(1)

  1. 出现场景
    master数据量会越来越大,一旦master重启,runid发生改变,会导致slave的全量复制,但是Redis内部有优化方案

  2. 优化方案

    • master内部有一个master-repl-id变量,长度41位(run id40位,相同的生成策略,后面多了个0),发送给slave
    • 在master关闭时只需shutdown save,进行RDB持久化,将runid和offset保存到RDB文件中
      • repl-id repl-offset
      • 通过redis-check-rdb命令可以查看


        image-20200831081000345.png
    • master重启的时候加载RDB的repl-id repl-offset
      • master_repl_id = repl-id master_repl_offset = repl-offset

      • info replication命令可以查看

  3. 作用:本机保存runid,重启后恢复该值,使得所有的slave都认为还是之前的master,所以不会进行全量复制

频繁的全量复制(2)

  1. 出现场景
    复制积压缓冲区太小+网络不好,导致断网后slave的offset越界了(master的缓冲器被新的指令挤走了),触发了全量复制,而且网络依然不好,再次触发全量复制,不断循环

  2. 优化方案:扩大复制积压缓冲区大小(2倍)

    repl-backlog-size

  3. 改成多少?


    image-20200831081925706.png

问题二:频繁的网络中断

频繁的网络中断(1)

  1. 出现场景

    slave调用了大量的慢查询(keys *,hgetall指令),CPU占用过高,会使得slave每1秒发送REPLCONF ACK命令无法发出,master发现slave长时间未响应

    白话:slave很忙,master不知道却一直呼叫,slave没理master

    现象:master的CPU占用过高(缓冲区满,带宽满),slave频繁的断开

  2. 优化方案

    设置合理的超时时间,超过则释放slave

    repl-timeout

    设置小:一次不经意的丢包,slave就给踢了

    设置大:资源浪费

频繁的网络中断(2)

  1. 出现场景
    master的ping指令频度低(10s才一次),若master的超时时间8s就会与slave断开,假设ping指令网络丢包
    现象:slave就会与master断开

  2. 优化方案
    提高ping指令的频度(5s就发一次确认)

  3. 如何设置ping频度和master超时时间?

    一般来说repl-timeout是ping频度的5~10倍,避免连接slave很容易被误判超时

问题三:数据不一致

  1. 出现场景:(树状的服务器结构,深度高)
    现象:多个slave获取数据不同步

  2. 解决方案

    • 优化主从的网络环境,放置同一个机房(阿里云要注意)

    • 空间主从节点延迟(offset),slave延迟大,可以屏蔽对slave的数据访问

      slave-serve-stale-data yes | no
      slave以允许提供过期数据

    • 开启后只允许响应info,slaveof等少数命令(调试)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容