Redis集群(1)主从复制 【转发】

0 摘要

主从同步机制三个阶段:

  • 第一次复制通过全量复制,全量复制完成之后(psync + RDB文件+repl_buffer);
  • 命令传播阶段(通过长连接+repl_buffer保证 命令顺序性+ repl_backlog_buffer 实现数据补发);
  • 恢复断连阶段增量同步(psync +repl_backlog_buffer )。redis 2.8之前和全量同步类似,通过psync代替sync实现增量同步。

命令传播阶段是否会出现:第一指令没有成功,第二个成功了?
不会。

1 全量复制和增量复制

1.1 全量复制

从节点与主节点第一次建联成功后执行全量同步流程如下:

  1. slave节点向master节点发送“psync ? -1” 命令;
  2. master收到psync命令之后返回 FULLRESYNC 告知 slave 将执行全量同步;
  3. master执行bgsave命令,Redis会fork出一个子进程在后台生成RDB文件,同时将同步过程中的写命令记录到replication_buffer中;
  4. master会把生成的RDB文件发送给slave;
  5. slave接收到RDB文件会将其装载入内存;
  6. master将记录在复制缓冲区replication_buffer的所有写命令发送给slave,slave对这些命令进行「重放」,将其数据库的状态更新至和master一致。
    如下图
    Redis集群(1)主从复制 【转发】_第1张图片

1.2 断连处理-增量复制

在Redis 2.8之前,如果因网络原因,主从节点复制中断,当再次建立连接时,还是会执行SYNC命令进行全量复制。效率较为低下。从Redis 2.8开始,引入了PSYNC命令代替SYNC命令来执行复制时的同步操作。PSYNC命令相比之前SYNC提供了增量复制。

注意: “PSYNC ? -1 ” 和SYNC作用相同,都是全量复制。

PSYNC通过复制挤压缓冲区repl_backlog_buffer实现增量复制,流程如下:
Redis集群(1)主从复制 【转发】_第2张图片

  1. 断连期间,主库将命令记录到repl_backlog_buffer,并更新master_repl_offset;
  2. 断连恢复,
    1)从库通过PSYNC ,发送salve_repl_offset 到主库
    2)主库将salve_repl_offset和master_repl_offset之间的数据发送给从库,即断连之间的数据
    注意:repl_backlog_buffer是环形缓存区,如果断连时间过长,主从不同步的命令超过缓冲区大小,此时会进行全量同步。

2 基于长连接的命令传播

解释下repl_backlog_buffer和replation_buffer两个缓存的区别?

replation_buffer每个长连接独享一个,建立主从连接之后生成的:
a:全量复制过程中,解决RDB生成、传输和加载过程中增量写问题;
b:命令传播过程中,实现命令按顺序同步到从节点。

relation_backlog_buffer所有长连接共享一个,redis服务初始化时候生成的:
a:恢复断连过程中实现增量复制;
b:命令传播过程中实现数据补发。

在命令传播阶段,一个写命令到master之后会更新两个buffer:
a:repl_backlog_buffer追加写命令;
b:replation_buffer追加写命令。

注意:redis7之后将上述两个缓冲区合并了,简称 共享复制缓冲区 ,具体可以查询相关文档

当主从库完成了全量复制,它们之间就会一直维护一个长连接,主库会通过这个长连接将后续陆续收到的写操作命令(replation_buffer中命令)发送给对应的从库,这个过程也称为基于长连接的命令传播,使用长连接的目的就是避免频繁建立连接导致的开销。
Redis集群(1)主从复制 【转发】_第3张图片

2.1 命令传播如何保证顺序性和完整性

假设,当前主从节点的repl_offset为1000,如下两个命令顺序达到主库:

  • 命令1 -> 保存到缓存repl_backlog_buffer (200个字节)&&更新master_repl_offset 1200 -> 异步发送命令给从节点offset。
  • 命令2 -> 保存到缓存repl_backlog_buffer(300个字节)&&更新offset 1500 -> 异步发送命令给从节点。

Q: 在将命令1和命令2同步到从库过程中是否出出现: 命令1丢失(失败)了,命令2正常写入从节点,即此时从节点offset为1300,然后从节点执行 REPLCONF ACK 1300,主从节点各如何处理?
A: 不会出现这个问题。分两种情况讨论:
  1)master保证命令按序同步给slave,因为主节点往从节点发送命令是通过replation_buffer进行的,replation_buffer是每个从节点长连接独享一个,所以保证了master同步到slave的命令的有序性,如上面命令传播流程图。
  2)slave收到命令后执行失败,这种情况下slave会主动断开长连接,然后重连会进行增量复制,保证命令不丢失。

2.2 心跳检测REPLCONF_ACK

在命令传播阶段,从节点间隔1秒向服务器发送一个“REPLCONF ACK{offset}” 命令。命令作用为:

  • slave上报资损复制偏移量,检查是否存命令丢失。主节点判断master_repl_offset和slave_repl_offset是否一致性,不一致性就行数据补发操作;
  • 判断master是否在线,如果超时则认为为master下线,1)将传播命令的长连接关闭;2)等下次进行心跳检查,如果连接上,则触发增量同步PSYNC
  • master确定从节点数量和每个从节点同步延迟时间,通过min-slaves-to-write、 minslaves-max-lag参数配置定义。

数据补发和增量复制区别:

  • 增量复制是主从连接断连,在连接恢复之后,从节点发送PSYNC 进行触发的;
  • 数据补发是在主从连接没有断连的情况下执行的。通过REPLCONF ACK{offset}触发。
    Redis集群(1)主从复制 【转发】_第4张图片

3 拓扑结构- 主-从-从

为了降级master同步的压力,多采用“主-从-从”的复制模式。
Redis集群(1)主从复制 【转发】_第5张图片

原文地址

你可能感兴趣的:(Redis,redis,redis主从复制)