分享

redis源代码分析-replication

 Foxmouse 2011-12-05

redis源代码分析-replication

九月 1, 2011 by · Leave a Comment 

edis的复制方法和机制都比较简单。

slaveof masterip port

在slave端键入命令之后,就开启了从master到slave的复制。一个master可以有多个slave,master有变化的时候会主动 的把命令传播给每个slave。slave同时可以作为其他的slave的master,前提条件是这个slave已经处于稳定状态 (REDIS_REPL_CONNECTED)。slave在复制的开始阶段处于阻塞状态(sync_readline)无法对外提供服务。

数据的有向图会让redis的运维很有搞头。

slaveof no one

从slave状态的转换回master状态,切断与原master的数据同步。

下面根据图形来描述一个复制全过程。

复制的顺序是从左到右。绿色的过程表示replstate复制状态的变迁,复制相关的函数主要在src/replication.c里,红色为master的复制函数,蓝色的为slave使用的复制函数。

slave端接收到客户端的slaveof masterip ort命令之后,根据readonlyCommandTable找到对应的函数为slaveofCommand。slaveofCommand会保存 masterip,masterport,并把server.replstate改成REDIS_REPL_CONNECT,然后返回给客户端OK。

slave端主线程在已经注册时间事件serverConn(redis.c 518)里执行replicationCron(redis.c 646)来开始与master的连接。调用syncWithMaster()开始与master的通信。经过校验之后,会发送一个SYNC command给master端,然后打开一个临时文件用于存储接下来master发过来的rdb文件数据。再添加一个文件事件注册 readSyncBulkPayload函数,这个就是接收rdb文件的数据的函数,然后修改状态为REDIS_REPL_TRANSFER。

master接收到SYNC command后,跳转到syncCommand函数(replication.c 556)。syncCommand会调度rdbSaveBackground函数,启动一个子进程做一个全库的持久化rdb文件,并把状态改为 REDIS_REPL_WAIT_BGSAVE_END。

master的主线程的serverCron会等待做持久化的子进程的退出,并判断退出的状态是否是正常。

if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {
if (pid == server.bgsavechildpid) {
backgroundSaveDoneHandler(statloc);
} else {
....

如果子进程正常退出,会转到backgroundSaveDoneHandler函数。backgroundSaveDoneHandler 处理每次rdbSaveBackground成功后的收尾工作,并打开刚刚产生的rdb文件。然后注册一个sendBulkToSlave函数用于发送 rdb文件,状态切换至REDIS_REPL_SEND_BULK。

sendBulkToSlave作用就是根据上面打开的rdb文件,读取并发送到slave端,当文件全部发送完毕之后修改状态为REDIS_REPL_ONLINE。

我们回到slave,上面讲到slave通过readSyncBulkPayload接收rdb数据,接收完整个rdb文件后,会清空整个数据库 emptyDb()(replication.c 374)。然后就通过rdbLoad函数载入接收到的rdb文件,于是slave和master数据就一致了,再把状态修改为 REDIS_REPL_CONNECTED。

接下来就是master和slave之间增量的传递的增量数据,另外slave和master在应用层有心跳检测(replication.c 543),和超时退出(replication.c 511)。

最后再给出一个replstate状态图

slave端复制状态

REDIS_REPL_NONE:未复制的状态

REDIS_REPL_CONNECT:已经接收到slaveof命令,但未发出sync命令给master

REDIS_REPL_TRANSFER:已经发出sync,但还没接收完rdb文件

REDIS_REPL_CONNECTED:已经接收完rdb文件,开始增量接收复制内容

maste端redis_client的复制状态

REDIS_REPL_WAIT_BGSAVE_START:bgsave被抢占,等待bgsave为其持久化进行工作。

REDIS_REPL_WAIT_BGSAVE_END:等待bgsave持久化rdb文件。

REDIS_REPL_SEND_BULK:rdb文件已经生成。开始拷贝给slave。

REDIS_REPL_ONLINE:rdb拷贝完毕,开始增量复制。

另外在syncCommand函数里有几种可能性

bgsave进程未启动,则启动。

bsave已启动,且已经存在另外的一个slave连接,已经由这个连接开启了bgsave,则等待bgsave完毕,共享这次的持久化。

bsave已启动,但不是由slave连接所启动的,则等待下次bgsave的退出。在updateSlavesWaitingBgsave函数里再次启动bgsave进程。

update:

 

关联性文章:
新浪微博开放平台Redis实战分享
Redis运维之道

浅谈redis数据库的键值设计
redis源代码分析-hash table
redis源代码分析-replication

redis源代码分析–protocol
redis源代码分析–persistence
redis源代码分析–event library

 

原创文章,转载请注明: 文章地址redis源代码分析-replication

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多