另外需要注意的是,每台Redis服务器都有一个运行ID,从服务器每次发送psync请求同步数据时,会携带自己需要同步主服务器的运行ID 。
主服务器接收到psync命令时,需要判断命令参数运行ID与自己的运行ID是否相等,只有相等才有可能执行部分重同步 。而当从服务器首次请求主服务器同步数据时,从服务器显然是不知道主服务器的运行ID,此时运行ID以“?”填充,同时复制偏移量初始化为-1 。
从上面的分析我们可以得到psync命令格式为“psync <MASTER_RUN_ID> <OFFSET>”,主从复制初始化流程如图1所示 。
从图1可以看到,当主服务器判断可以执行部分重同步时向从服务器返回“+CON-TINUE”;需要执行完整重同步时向从服务器返回“+FULLRESYNC RUN_ID OFFSET”,其中RUN_ID为主服务器自己的运行ID,OFFSET为复制偏移量 。

文章插图
▲图1 主从复制初始化流程图
可以看到执行部分重同步的要求还是比较严格的:
- RUN_ID必须相等;
- 复制偏移量必须包含在复制缓冲区中 。
- 从服务器重启(复制信息丢失);
- 主服务器故障导致主从切换(从多个从服务器重新选举出一台机器作为主服务器,主服务器运行ID发生改变) 。
- 方案1:持久化主从复制信息
if (rdbSaveAuxFieldStrStr(rdb,"repl-id",server.replid) == -1) return -1; if (rdbSaveAuxFieldStrInt(rdb,"repl-offset",server.master_repl_offset) == -1) return -1;
- 方案2:存储上一个主服务器复制信息
void shiftReplicationId(void) { memcpy(server.replid2,server.replid,sizeof(server.replid)); server.second_replid_offset = server.master_repl_offset+1; changeReplicationId();}另外判断是否能执行部分重同步的条件也改变为:
if (strcasecmp(master_replid, server.replid) && (strcasecmp(master_replid, server.replid2) || psync_offset > server.second_replid_offset)){ goto need_full_resync;}假设m为主服务器(运行ID为M_ID),A、B和C为三个从服务器;某一时刻主服务器m发生故障,从服务器A升级为主服务器(同时会记录replid2=M_ID),从服务器B和C重新向主服务器A发送“psync M_ID psync_offset”请求;显然根据上面条件,只要psync_offset满足条件,就可以执行部分重同步 。
关于作者:李乐,好未来php工程师,西安电子科技大学硕士,乐于钻研技术与源码研究,对Redis和Nginx有较深理解 。合著书籍《Redis 5设计与源码分析》 。
本文摘编自《Redis 5设计与源码分析》,经出版方授权发布 。
【Redis如何高效可靠地实现主从复制?终于有人讲明白了】
推荐阅读
- 如何优化Mac电脑
- 浪潮TS850服务器,MegaRAID卡,如何做RAID?
- 什么是算法?如何学习算法?算法入门的学习路径
- 浙江省|2022 年应届生如何找到适合自己的工作?
- 如何增强体力和耐力?
- 硼砂对皮肤有伤害吗,如何预防
- 团购是怎么回事 如何看待网络团购是个陷阱
- 龙井 茶文化入世遗 西安千年茶韵如何传承
- 夏季如何挑选太阳镜?掌握这3个原则
- 如何拯救干性肌肤?靓你帮你支几招,好皮肤就是这么简单
