主从复制简单来说就是把一台复述,数据库中的数据同步到另一台复述,数据库,并且按照数据流向,数据的发送者我们称作主人,数据的接受者我们称作奴隶(主/从的划分并不是那么一定的,譬如B可以作为一的奴隶,但同时也可以作为C的主人),下面就从奴隶和主人的角度分别说明主从复制流程只
首先是奴隶端,对于奴隶端来说,主从复制主要经历四个阶段:,
第一阶段:与主建立连接,
第二阶段:向主人发起同步请求(同步),
第三阶段:接受主人发来的RDB数据,
第四阶段:载入RDB文件,
下面我们就通过一个图来概述在每一个阶段中,奴隶究竟做了些什么:,
%20
- %20<李>%20
,%20serverCron%20():,,%20
%20李>%20<李>,,%20
%20李>%20<李>%20,%20redisServer.repl_state ==,%20REDIS_REPL_CONNECT:,,%20
%20李>%20<李>,,%20
%20李>%20<李>%20%20
%20李>%20<李>,,%20
%20李>%20%20
%20
接着我们来看下主从复制过程中,主人这边的流程是如何,在具体看细节之前,我们先综合来看主人这边主要做的几件事情:,
%20
%20,
看完这个图,你也许会有以下几个疑问:,
1。为什么在主发送完RDB文件后,还要定期的向奴隶发送平命令?
2。在发送完RDB文件之后,master发送的“变更”命令又是什么,有什么用?
在回答问题之前1,我们先回答问题2:
master保存RDB文件是通过一个子进程进行的,所以master依然可以处理客户端请求而不被阻塞,但这也导致了在保存RDB文件期间,“键空间”可能发生变化(譬如接收到一个客户端请求,执行"set name diaocow"命令),因此为了保证数据同步的一致性,master会在保存RDB文件期间,把接受到的这些可能变更数据库“键空间”的命令保存下来,然后放到每个slave的回复列表中,当RDB文件发送完master会发送这些回复列表中的内容,并且在这之后,如果数据库发生变更,master依然会把变更的命令追加到回复列表发送给slave,这样就可以保证master和slave数据的一致性!相关伪代码:
Python代码
processCommand(cmd, argc, argv):
redisServer.update_key_space len(redisServer.slaves) > :
replicationFeedSlaves(cmd, argc, argv):
slave redisServer.slaves:
slave.replstate == REDIS_REPL_WAIT_BGSAVE_START:
由于在发送完RDB文件之后,master会不定时的给slave发送“变更”命令,可能过1s,也可能过1小时,所以为了防止slave无意义等待(譬如master已经挂掉的情况),master需要定时发送“保活”命令PING,以此告诉slave:我还活着,不要中断与我的连接
现在我们就看下,当master接受到slave发送的sync同步命令后究竟发生了哪些事:
上图看似分支复杂,但我们抓住以下几点即可:
1.保存RDB文件是在一个子进程中进行的;
2.如果master已经在保存RDB文件,但是没有客户端正在等待这次BGSAVE,新添加的slave需要等到下次BGSAVE,而不能直接使用这次生成的RDB文件(原因图中已经说明)