技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 源码分析 --> redis源代码分析 - replication

redis源代码分析 - replication

浏览:3488次  出处信息

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

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:

""

建议继续学习:

  1. redis源代码分析 - persistence    (阅读:31229)
  2. 关于IO的同步,异步,阻塞,非阻塞    (阅读:14551)
  3. Redis消息队列的若干实现方式    (阅读:10771)
  4. 基于Redis构建系统的经验和教训    (阅读:9385)
  5. 浅谈redis数据库的键值设计    (阅读:8348)
  6. redis在大数据量下的压测表现    (阅读:7441)
  7. redis运维的一些知识点    (阅读:7517)
  8. Redis和Memcached的区别    (阅读:6892)
  9. Redis作者谈Redis应用场景    (阅读:6625)
  10. redis 运维实际经验纪录之一    (阅读:6532)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1