浅谈redis主从复制的replication buffer 和 replication backlog

背景:

由于最近刚搭了redis的哨兵模式集群,就了解了下redis的主从复制。在此记录下一些知识点。

首先,我们先说redis的主从复制原理,再说那两个参数。

异步复制

redis是使用默认的异步复制,slave 和 master 之间异步地确认处理的数据量。

redis复制依靠三个主要的机制:

  • 当一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave的更新,以便于将自身数据集的改变复制给 slave :包括客户端的写入、key 的过期或被逐出等等。
  • 当 master 和 slave 之间的连接断开之后,因为网络问题、或者是主从意识到连接超时, slave 重新连接上 master,并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流。
  • 当无法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,例如 master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave

Redis 复制功能的工作原理

每一个 Redis master 都有一个 replication ID :这是一个较大的伪随机字符串,标记了一个给定的数据集。每个 master 也持有一个偏移量master 将自己产生的复制流发送给 slave 时,发送多少个字节的数据,自身的偏移量就会增加多少,目的是当有新的操作修改自己的数据集时,它可以以此更新 slave 的状态。复制偏移量即使在没有一个 slave 连接到 master 时,也会自增,所以基本上每一对给定的

Replication ID, offset

都会标识一个 master 数据集的确切版本。

当 slave 连接到 master 时,它们使用 PSYNC命令来发送它们记录的旧的 master replication ID 和它们至今为止处理的偏移量。通过这种方式, master 能够仅发送 slave 所需的增量部分。但是如果 master 的缓冲区中没有足够的命令积压缓冲记录,或者如果 slave 引用了不再知道的历史记录(replication ID),则会转而进行一个全量重同步:在这种情况下, slave 会得到一个完整的数据集副本,从头开始。

下面是一个全量同步的工作细节:

master 开启一个后台保存进程,以便于生产一个 RDB 文件。同时它开始缓冲所有从客户端接收到的新的写入命令。当后台保存完成时,master 将数据集文件传输给 slave, slave将之保存在磁盘上,然后加载文件到内存。再然后 master 会发送所有缓冲的命令发给 slave。这个过程以指令流的形式完成并且和 Redis 协议本身的格式相同。

如果 master 收到了多个 slave 要求同步的请求,它会执行一个单独的后台保存,以便于为多个 slave 服务。

由上面可知,redis的主从复制可分为两个阶段:

1)同步(sync rdb snapshot):slave复制master的某时间点(t)的全量数据,t为master接收到slave的sync命令后执行rdb bgsave的时间点。master发送rdb文件到slave,slave读取rdb把数据加载到内存。

2)命令传播(commands propagation):同步时间点t后master上的数据更新到slave上, 发送的数据是redis的命令。

SYNC: 是一个旧协议,在新的 Redis 实例中已经不再被使用,但是其仍然向后兼容:但它不允许部分重同步。2.8增加psync,支持full resync和partial resync命令,现在 PSYNC被用来替代 SYNC。

1.replication buffer的作用

replication buffer里面存放的数据是下面三个时间内所有的master数据更新操作:

  • master执行rdb bgsave产生snapshot的时间
  • master发送rdb到slave网络传输时间
  • slave load rdb文件把数据恢复到内存的时间

replication buffer由client-output-buffer-limit slave参数设置,当这个值太小会导致主从复制链接断开。从而引发:

1)当master-slave复制连接断开,server端会释放连接相关的数据结构。replication
buffer中的数据也就丢失了,此时主从之间重新开始复制过程。
2)还有个更严重的问题,主从复制连接断开,导致主从上出现rdb bgsave和rdb重传操作无限循环。

于是查看了一下client-output-buffer-limit。发现这是Redis的一个保护机制。配置格式是:

 client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>

具体参数含义如下:

  • class: 客户端种类,包括Normal,Slaves和Pub/Sub

    • Normal: 普通的客户端。默认limit 是0,也就是不限制。
    • Pub/Sub: 发布与订阅的客户端的。默认hard limit 32M,soft limit 8M/60s。
    • Slaves: 从库的复制客户端。默认hard limit 256M,soft limit 64M/60s。
  • hard limit: 缓冲区大小的硬性限制。

  • soft limit: 缓冲去大小的软性限制。

  • soft seconds: 缓冲区大小达到了(超过)soft limit值的持续时间。

配置文件的默认配置如下:

client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

redislab关于该参数的说明,推荐把slave replication buffer的hard/soft limit设置成512M

2、replication backlog的出现

在2.8版本,redis使用了新的复制方式,引入了复制积压缓冲(replication backlog)
在这里插入图片描述

上图来自《redis设计与实现》

当主服务器进行命令传播的时候,maser不仅将所有的数据更新命令发送到所有slave的replication buffer,还会写入replication backlog。当断开的slave重新连接上master的时候,slave将会发送psync命令(包含复制的偏移量offset),请求partial resync。如果请求的offset不存在,那么执行全量的sync操作,相当于重新建立主从复制。

3.区分replication buffer 和 replication backlog

1) replication buffer对应于每个slave,通过config set client-output-buffer-limit slave 设置。

2) replication backlog是一个环形缓冲区,整个master进程中只会存在一个,所有的slave公用。backlog的大小通过repl-backlog-size参数设置,默认大小是1M。
其大小可以根据每秒产生的命令 乘以((master执行rdb bgsave的时间)+ (master发送rdb到slave的时间) + (slave load rdb文件的时间) ) ,来估算积压缓冲区的大小,repl-backlog-size值不小于这两者的乘积。

总结

由此可见,Redis的主从同步非常依赖于两个参数的合理配置:

  • client-output-buffer-limit
  • repl-backlog-size

参考链接:

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值