Redis 数据同步机制

Redis的主从同步机制可以确保redis的master和slave之间的数据同步。Redis在2.8及以上版本使用psync命令完成主从数据同步。同步方式包括:全量复制和增量复制

1. 同步机制

  • 全量复制

全量复制

  1. slave第一次启动时,连接Master,发送PSYNC命令,格式为psync {runId} {offset}
  • {runId} 为master的运行id;{offset}为slave自己的复制偏移量
  • 由于此时是slave第一次连接master,slave不知道master的runId,也不知道自己偏移量,这时候会传一个问号和-1,告诉master节点是第一次同步。格式为psync ? -1
  1. 当master接收到psync ? -1时,就知道slave是要全量复制,就会将自己的runIdoffset告知slave,回复命令+fullresync {runId} {offset}。同时,master会执行bgsave命令来生成RDB文件,并使用缓冲区记录此后的所有写命令
  • slave接受到master的回复命令后,会保存master的runIdoffset
  • slave此时处于同步状态,如果此时收到请求,当配置参数slave-server-stale-data yes时,会响应当前请求,no则返回错误。
  1. master bgsave执行完毕,向Slave发送RDB文件,同时继续缓冲此期间的写命令。RDB文件发送完毕后,开始向Slave发送存储在缓冲区的写命令
  2. slave收到RDB文件,丢弃所有旧数据,开始载入RDB文件;并执行Master发来的所有的存储在缓冲区里的写命令。
  3. 此后 master 每执行一个写命令,就向Slave发送相同的写命令。
  • 增量复制

  1. 如果出现网络闪断或者命令丢失等异常情况时,当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行ID。因此会把它们当作psync参数发送给主节点,要求进行部分复制操作,格式为psync {runId} {offset}
  2. 主节点接到psync命令后首先核对参数runId是否与自身一致,如果一致,说明之前复制的是当前主节点;之后根据参数offset在自身复制积压缓冲区查找,如果偏移量之后的数据存在缓冲区中,则对从节点发送+CONTINUE响应,表示可以进行部分复制;否则进行全量复制。
  3. 主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态

2. 注意事项

  • 复制超时

对于数据量较大的主节点,比如生成的RDB文件超过6GB以上时要格外小心。传输文件这一步操作非常耗时,速度取决于主从节点之间网络带宽,通过细致分析Full resync和MASTERSLAVE这两行日志的时间差,可以算出RDB文件从创建到传输完毕消耗的总时间。如果总时间超过repl-timeout所配置的值(默认60秒),从节点将放弃接受RDB文件并清理已经下载的临时文件,导致全量复制失败。

针对数据量较大的节点,建议调大repl-timeout参数防止出现全量同步数据超时。

例如对于千兆网卡的机器,网卡带宽理论峰值大约每秒传输100MB,在不考虑其他进程消耗带宽的情况下,6GB的RDB文件至少需要60秒传输时间,默认配置下,极易出现主从数据同步超时。

  • 输出缓冲区溢出

对于Redis服务器的输出(也就是命令的返回值)来说,其大小通常是不可控制的。有可能一个简单的命令,能够产生体积庞大的返回数据。另外也有可能因为执行了太多命令,导致产生返回数据的速率超过了往客户端发送的速率,这是也会导致服务器堆积大量消息,从而导致输出缓冲区越来越大,占用过多内存,甚至导致系统崩溃。

所幸,Redis设置了一些保护机制来避免这种情况的出现,不同类型的客户端有不同的限制参数。限制方式有如下两种:

(1)、大小限制,当某一个客户端的缓冲区超过某一个大小值时,直接关闭这个客户端的连接;
(2)、持续性限制,当某一个客户端的缓冲区持续一段时间占用过大空间时,会直接关闭客户端连接。

我们来看看配置文件关于客户端输出缓冲区的配置:

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

不同客户端有不同策略,策略如下:

  1. 对于普通客户端来说,限制为0,也就是不限制。因为普通客户端通常采用阻塞式的消息应答模式,何谓阻塞式呢?如:发送请求,等待返回,再发送请求,再等待返回。这种模式下,通常不会导致Redis服务器输出缓冲区的堆积膨胀;

  2. 对于Pub/Sub客户端(也就是发布/订阅模式),大小限制是8M,当输出缓冲区超过8M时,会关闭连接。持续性限制是,当客户端缓冲区大小持续60秒超过2M,则关闭客户端连接;

  3. 对于slave客户端来说,大小限制是256M,持续性限制是当客户端缓冲区大小持续60秒超过64M,则关闭客户端连接。

上述三种规则都是可以修改的。可以通过CONFIG SET 命令设置或者直接修改redis.conf文件。

  • slave全量同步时的响应问题

slave节点接收完主节点传送来的全部数据后会清空自身旧数据,执行flash old data,然后加载RDB文件。对于较大的RDB文件,这一步操作依然比较耗时。

对于线上做读写分离的场景,从节点也负责响应读命令,如果slave节点正处于全量复制阶段,那么slave节点在响应读命令可能拿到过期或错误的数据。对于这种场景,Redis复制提供了slave-server-stale-data yes参数,默认开启状态。如果开启则slave节点依然响应所有命令。对于无法容忍不一致的应用场景可以设置no来关闭命令执行,此时从节点除了info和slaveof命令之外所有的命令只返回SYNC with master in progress信息

3. 解释

  • 节点运行IDrunId

  1. 每个Redis节点启动后都会动态分配一个40位的十六进制字符串作为运行ID。运行ID的主要作用是用来唯一识别Redis节点,比如从节点保存主节点的运行ID识别自己正在复制的是哪个主节点。

  2. 如果只使用ip+port的方式识别主节点,那么主节点重启变更了整体数据集(如替换RDB/AOF文件),从节点再基于偏移量复制数据将是不安全的,因此当运行ID变化后从节点将做全量复制。

  3. 可以运行info server命令查看当前节点的运行ID

  • 复制偏移量offset

  1. 参与复制的主从节点都会维护自身复制偏移量。

  2. 主节点(master)在处理完写入命令后,会把命令的字节长度做累加记录,统计信息在info relication中的 master_repl_offset 指标中

  3. 从节点(slave)在接收到主节点发送的命令后,也会累加记录自身的偏移量,统计信息在info relication中的slave_repl_offset指标中

  4. 从节点(slave)每秒钟上报自身的复制偏移量给主节点,因此主节点也会保存从节点的复制偏移量,

  • 复制积压缓冲区

  1. 存在于主节点(master),默认大小为1MB,可以通过参数rel_backlog_size来修改默认大小

  2. 复制积压缓冲区是保存在主节点上的一个固定长度的队列。当从节点(slave)连接主节点时被创建,这时主节点(master)响应写命令时,不但会把命令发送给从节点,还会写入复制积压缓冲区。

  3. 由于缓冲区本质上是先进先出的定长队列,所以能实现保存最近已复制数据的功能,用于部分复制和复制命令丢失的数据补救。复制缓冲区相关统计信息保存在主节点的info replication中。



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值