redis2.6版本主从复制功能详解

本文以redis2.6源码为例详细介绍主从模式的复制功能。流程图见文末
#### 1.复制流程 (从服务器视角)

---
- 假设redis服务器A收到客户端发来的slaveof 192.168.1.89 6379命令,则服务器会检查当前是否已连接主服务器,如果已连接且是192.168.1.89 6379,则什么也不做。
否则清除A的所有从服务器,并在下一个serverCron中连接到192.168.1.89:6379 (假设为服务器B),此时A成为B的客户端,假设描述符为fd,并为此fd安装事件(读写)处理函数
syncWithMaster.

- 随后在下一次事件循环中,A向B发送PING命令。正常来讲,A会在下一个事件循环中收到B发来的PONG。如果向A配置了连接密码后,则A会继续发送AUTH PASS到B来进行认证。

- 随后A会继续发送REPLCONF listening-port port到B,用来告知自己的监听端口。

- 随后A会继续发送SYNC命令请求同步RDB文件,并且准备临时文件用来接收文件,并为fd绑定事件读处理函数readSyncBulkPayload。随后B会源源不断地发送RDB文件给A,并在每次事件循环中通过readSyncBulkPayload来对收到的数据进行处理。

- 在下一次(也可能是下下...次)事件循环中readSyncBulkPayload会首先得到rdb文件的大小,随后开始接收,并将接收到的内容写到文件,同时使用fsync同步到磁盘。

- 接收文件并写到本地磁盘。重复该步骤直到文件传输完毕。

- 当文件接收完毕时,A会将RDB临时文件重命令为RDB文件,一般会是dump.rdb。然后将A的所有客户端只要watch了某个键,则将该客户端标记为脏。此做法为了实现事务。然后清空数据库。
再重新加载刚才的dump.rdb文件。再为fd绑定读事件处理函数readQueryFromClient(此时B成为了A的客户端)。

- 随后B会将RDB持久化期间的命令缓存以客户端的身份发送给A,A会执行这些命令。


结束。。。


---

#### 2.复制流程 (主服务器视角)

---
- 服务器B收到A的ping后会回复PONG

- 在下一个事件循环中会收到sync命令,并且执行syncCommand。该接口会进行下面合法性校验:
- 该接口会首先判断该客户端(A)是否是slave,若是则直接返回,啥也不做。
- 如果自己是其它服务器的从服务器且复制状态不是REDIS_REPL_CONNECTED,则报告错误。这里要说明的是redis允许多级主从模式,即从服务可以有自己的从服务器。
- 如果当前客户端缓冲区有待发送的消息,则直接报告错误并返回。

- 合法性校验后会判断当前是否有后台rdb持久化操作:
- 若有,则判断是否已经有从客户端在等等持久化完毕,若有(这里假设已经有客户端c在等等rdb持久化完成),则将c的缓冲区内容拷贝到当前客户端A,并将客户端A的状态置为等待RDB持久化完成,若没有,很不幸,则需要进行重新持久化,并将客户端A的状态置为等待RDB持久化开始。
- 若没有,则进行后台RDB持久化,并将客户端A的状态置为等待RDB持久化完成。

- 由上所述若需要进行重新rdb持久化,则主进程会fork出子进程进行持久化。
重要!!! 此时如果有其它客户端的IO事件发生,比如set命令或其它能改变数据库内容的命令执行时,会将该命令拷贝到所有等待RDB持久化完成的从服务器的缓冲内。

- 在随后的时间事件循环中即serverCron中会判断RDB持久化是否完成,若完成,则判断是否有等待RDB持久化完成的从服务器,若有(A),则将A的描述符挂载写事件函数sendBulkToSlave,在随后的事件循环中会发送rdb文件。

- 在后来的文件事件循环中会持续调用sendBulkToSlave来给A发送文件。首次发送rdb文件时会先发送文件大小给A。
直到文件发送完毕后,会重新给A绑定写事件sendReplyToClient,用来发送A的缓冲区中的命令。

结束。。


---

#### 3.注意事项

---
- 3.1 由于在rdb持久化期间,主进程仍然可以执行客户端发来的写命令,那么发送给从服务器的rdb文件并不代表完整的数据库副本呀。

答:
> 只要从服务器的状态不是REDIS_REPL_WAIT_BGSAVE_START(等待rdb持久化开始),那么任意的可以改变数据库内容的命令都会追加到从服务器的缓冲区内。当rdb传送完毕后,主服务器会将从服务器缓冲区内的命令发给从服务器,从服务器收到后会执行这些命令,通过这样来达到数据库的完整性。

- 3.2 为什么主服务器不一次性将rdb文件发给从服务器,而要分多次事件循环发送?

答:
> 由于rdb文件都比较大,如果一次性全部发过去,这样会阻塞主服务器,使其它客户端的命令得不到迅速执行。

---

#### 4.你们要的流程图
由于电脑 没装visio,也懒得安装了。就用了个在线流程图制作工具,大家可以试用下,也挺方便[processon](https://www.processon.com)
[请点击看高清原图](https://www.processon.com/view/link/5a12bb69e4b06c8e109384e0)

posted @ 2018-02-09 15:00  好想吃肉  阅读(84)  评论(0)    收藏  举报