Redis主从复制机制分析

来源:互联网 发布:reeder 3 for mac 编辑:程序博客网 时间:2024/06/05 22:45

前言

   作者阅读了《Redis设计与实现》(第二版)replication章节。想更深地了解replication机制。于是分析了Redis 3.2.8源码。并编写了这篇文章。如有分析不对的地方,还请各位包涵,指正。

Slave端分析Replication机制

 

    将Redis实例设置成Slave。主要流程,见下图。

         第一步在replication.c:saveofComand函数中完成。在此函数中,起主要作用的函数是replicationSetMaster。此函数保存MasterIP和端口号。并将replication的状态设置为REPL_STATE_CONNECT。此状态为Slave状态。

 

        第二步,在replication.c:replicationCron函数中执行。此函数1秒中被调用一次。此函数检查到slave的状态为REPL_STATE_CONNECT,就开始调用函数connectWithMaster函数,创建连接MasterTCP连接。

 

  第三步,在connectWithMaster函数中完成。在此函数中,创建了连接MasterTCP。此TCP连接为异步非阻塞连接。它为此连接的可读事件和可写事件,注册了回调函数syncWithMaster。并将slave的状态,切换到正在连接的状态。状态值为REPL_STATE_CONNECINGsyncWithMaster函数完成后续的同步操作。

 

 

  当与Master的连接建立好后,socket可读。触发syncWithMaster函数。此函数执行了一个状态机。状态机见下图:


    在发送PSYNC时,程序会调用slaveTryPartialResynchronization(fd, 0)。发送PSYNC命令。此函数根据Slave的状态发送两种PSYNC命令。当为Slave连接过Master这种情况,发送PSYNC  <master run id>  <repl offset>。尝试部分同步。当没有连接过Master这咱情况,发送PSYNC  ?  -1  尝试完全同步。

   

   在进入接收PSYNC状态后,程序调用slaveTryPartialResynchronization(fd, 1)来解析Master的对PSYNC命令的响应。此函数有四种返回值。

   当返回PSYNC_WAIT_REPLY时,表示Master还没有响应。程序在下一次响应读事件时,会继续调用此函数。

当返回PSYNC_FULLRESYNC时,表示MasterSlave发送了全部同步的响应。在返回PSYNC_FULLRESYNC之前,此函数已经执行了此socket的可读事件属性。之后,程序将不再调用syncWithMaster

当返回PSYNC_CONTINUE时,表示开始部分同步操作。之后,程序也不会再调用syncWithMaster了。

当返回PSYNC_NOT_SUPPORTED时,表示Master不支持PSYNC命令。程序之后会向Master发送SYNC命令。之后开始完全同步。

 

   syncWithMaster函数调用laveTryPartialResynchronization(fd, 1)之后。若返回值为PSYNC_CONTINUE。则在replicationResurrectCachedMaster函数中,将socket的可读事件处理回调函数换成了networking.c:readQueryFromClient函数。此函数将可读事件放入事件循环中。替换完之后,Master发送来的命令,可直接进入Slave的事件循环。完成backlog的同步。同步完之后,Master会将它接收到的命令,调用replicatoinFeedSlaves函数,发送给slave,完成MasterSlave的实时同步。

 

   syncWithMaster函数调用laveTryPartialResynchronization(fd, 1)之后。若返回值为SYNC_FULLRESYNC。则进入执行完全同步。将socket的可读事件回调函数换成readSyncBulPayload。之后将slave的状态切换成REPL_STATE_TRANSFER

readSyncBulPayload函数会接收master生成的数据库rdb文件。接收完之后,会加载这个rdb文件。

 

   SlaveMaster之间的交互信息,见下图:



   问题:开始执行完全同步到执行完,这段时间内,Master接收了一些新的命令。同步完全成之后,这些命令是怎么传递过来的?

 

 

Master端分析Replication机制

    SlaveMaster发送PSYNC命令。Master使用函数syncCommand响应此命令。此函数为Master端主从复制的入口。

    syncComand函数流程图如下:


    其中检查是否为部分同步和完成部分同步的逻辑(a1-a2),见下图:


  执行完全同步(a3)的逻辑见下图:


    以上三图就是syncComand函数的主要逻辑。

 

    A1,a2对应的主要代码为replication.c:masterTryPartialResynchronization函数。masterTryPartialResynchronization函数调用了addReplyReplicationBacklog函数,完成了C6所代指的内容。

 

    syncCommand调用了startBgsaveForReplicatoin来执行应完全重新同步操作。syncCommand命令在开启复制数据库子进程之后,在执行了其它一些操作之后,就退出了。并没有执行发送生成的数据库文件等剩余的同步操作。在server的定时回调函数(server.c:serverCron),执行以下操作:


    由rdb.c:backgroundSaveDoneHandler函数,执行以上操作。

 在执行d4操作之后,回调函数换成sendBulkToSlave。由这个函数发送生成的rdb文件。

 每当masterslave的连接可写时,都会调用sendBulkToSlave函数。此函数的流程图如下:


  至此,分析完了redis主从复制机制。还有些细节,不影响分析其主体架构。就不描述了。

 

未清楚的地方

  在发送完rdb文件后,程序是如何同步在生成rdb文件期间累积的命令的?虽然,能从代码里猜测出其实现方法。但未完全搞清楚。待日后分析。



0 0
原创粉丝点击