Redis Psync机制

Redis Psync机制

后台同步操作

Redis在初始化时,会创建一个叫ServerCron的Time Event,定期处理全部后台操作。

ServerCron中,有一个replicationCron进程,以每1s一次的频率调用,用于重连master,检测传输失败,启动后台RDB传输等同步操作。

replicationCron

  1. 检查是否发生连接超时;
  2. 检查是否发生IO传输超时;
  3. 检测是否允许连接到Master,通过connectWithMaster()连接,打印一条日志:"MASTER <-> SLAVE sync started"
  4. 向Master返回ACK消息。
  5. 如果有连接的SLAVES,发送PING消息,使SLAVES实现超时机制,并检测连接有效性。
  6. 向所有在pre-synchronization阶段(等待master创建RDB文件)的SLAVES发送一个换行符,令其刷新last-io定时器。
  7. 断开超时的SLAVES。
  8. 开始为replication的BGSAVE,目标根据配置可以是硬盘或socket(DISKLESS复制方式)。
  9. 刷新SLAVES数量,满足lag<=min-slaves-max-lag的为GOOD SLAVES。

connectWithMaster

  1. anetTcpNonBlockBestEffortBindConnect: 连接到master
  2. 创建用于同步的readable event:syncWithMaster

syncWithMaster交互

  1. PING -> PONG
  2. AUTH -> AUTH reply
  3. REPLCONF listening-port -> REPLCONF listening port reply
  4. REPLCONF ip-address -> REPLCONF ip-address reply
  5. REPLCONF capa -> REPLCONF capa reply
  6. slaveTryPartialResynchronization:尝试部分重同步。
如果没有缓存的master,则开启一次完全重同步(相当于触发“psync ? -1”命令),以获取
master的run-id和全局offset,返回PSYNC_FULLRESYNC。先执行write half,
再执行read half,如果需要下一次调用,返回PSYNC_WAIT_REPLY。
如果正常执行局部重同步,返回PSYNC_CONTINUE。

syncCommand

完全同步和部分重同步在Redis内部都是通过SyncCommand实现。

  1. 如果客户端发送的是psync命令,则进入masterTryPartialResynchronization(),进行部分重同步。
  2. 如果客户端发送的是sync命令,或者部分重同步返回失败,则进行完全重同步。
  3. 过程:
server.repl_backlog_off + server.repl_backlog_histlen)的缓冲区间里,日志
打印"Unable to partial resync with slave %s for lack of backlog (Slave
 request was: %lld)." 如果psync_offset甚至都超前于
 server.master_repl_offset, 日志打印"Warning: slave %s tried to PSYNC
  with an offset that is greater than the master replication offset."
  1. 实施部分重同步:

    • 设置客户端标记为SLAVE:c->flags |= CLIENT_SLAVE;
    • 响应客户端“+CONTINUE”,表示可以继续部分重同步;
    • 发送backlog数据(offset到末尾)数据给SLAVE。
  2. refreshGoodSlavesCount()

FAQ

  1. REPLCONF命令的capa参数包括哪些?
    答:目前master接受的只有REPLCONF CAPA EOF,定义了RDB的EOF流格式,其余能力定义master都暂时还无法理解。
  2. 全量同步是否是向目标发送从master启动开始的全部的数据?
    答:是。内部会做一次BGSAVE操作,然后将整个RDB DUMP到目标文件,然后将RDB文件发给SLAVE,最后SLAVE LOAD接收到的RDB文件;或者直接socket传输(无盘模式)。

  3. 全量同步期间产生的更新操作太多,是否会导致下次增量同步的offset落后再次触发全量同步?
    答:不会。全量同步期间产生的更新操作,并不放在repl_backlog里,会在全量同步的最后一步,将Master在快照内过程中的所有更新操作发给Slave。

你可能感兴趣的:(Redis Psync机制)