探索mysql和redis主从复制的实现原理

前几天跟同事聊了下常见数据库的主从复制是怎么个原理。 另外对于redis的主从数据同步颇有些心得,就跟大家唠唠。

该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新. http://xiaorui.cc/?p=3332


Mysql主从同步:

Mysql master slave是最常见的主从模式,原理还算简单,就是master把用户的行为都记录到binlog里面 ( 除了select ) , 虽然binlog是二进制的文件,你用mysql的showbinlog可以看到那都是一条条的sql语句。 对于从主机来说,我只要知道偏移量就可以了,mysql主从关系的偏移量指的是pos 、file记录。   对于master来说,我知道从现在的offset偏移量,我根据他提供的pos及file值就可以从本地磁盘里捞出文件,然后send数据给slave节点。  我上面说的是基本流程,其实mysql的实现要比这复杂,比如5.5之后出现半同步。

mysql的主从复制说的有些粗略。我近几年不知道为毛总是喜欢刨根问底,看到一个有意思的服务就想看看他的源码实现。 对于mysql来说, 我是本想从源码层面解读mysql主从原理,但我个人能力有限,又没时间看这代码。 

下面我们开始研究下redis的主从复制是怎么一回事。  他跟mysql主从又有啥区别? 

Redis的主从是不需要类似binlog这样的日志记录,有些意思. 

Redis主从同步:

Redis的同步分为全部同步及部分同步。  对应到mysql的操作步骤,全部同步,使用xtrabackup做完整备份。  部分同步,通过pos,file做增量同步,也就是部分同步。 

当我们redis slave客户端连接redis master的时候,master会判断slave是否为第一次同步.  redis master后面不单单是靠IP及PORT识别用户,更主要的是通过slave提交的runid标志来识别客户端。 

如果判定为第一次同步,master首先会注册一个监听器,这个监听器主要用来收集用户的命令。 这些命令放在一个叫积压空间的数据结构里,之后再fork一个子进程调用bgsave函数进行RDB快照。 fork子进程的速度是很快的,因为是cow 写实拷贝,意思就是说,子进程只是复制父进程的页表,然后物理内存页帧是一样的。 当父进程 或者 子进程要修改数据的时候,内核才会copy数据到独立的页帧。 
如果判定为不是第一次同步,那么客户端会根据你的offset偏移量返回数据。  但是这里也是有个判断条件的,如果slave长期没有连接master,他的next offset在我的环形队列中早已经没有,那么你走的还是RDB得那个流程。 反之你的offset在我的记录中,那么我会返回命令可以。 

假设你当前的偏移量为200, 如果主服务器又执行了命令 SET blog xiaorui.cc (协议格式的长度为 33 字节), 将自己的复制偏移量更新到了 233 , 并尝试向从服务器c传播这条指令。 但这条命令却因为网络故障而在传播的途中丢失, 那么主从服务器之间的复制偏移量就会出现不一致: 主服务器的复制偏移量会被更新为 233 , 而从服务器的复制偏移量仍然为 200。

这nima主从之间的数据不同步怎么办?   数据不一致是个很场景的问题。 

这问题不大,因为slave每次做同步的时候都会拿着自己上次的offset。 这时候master记着你是233,但这时候你居然提交了200.   那master会顺从slave的意思,你要啥就给你啥。 

在redis里面创建主从特别的容易,创建主—> 从—>从 关系也是相当的容易。不像是mysql那样,都需要开启binlog日志,server-id也要配置,还要针对从开启update-slave-log选项,这样可以保证从也会写binlog。  对于redis来说,你只要发送sync指令,我就可以根据你的offset状态来发送数据。  

下面就是redis的Master Slave同步的流程图. 

END.


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

4 Responses

    • rfyiamcool 2016年5月16日 / 下午3:33

      那啥,这个是go的mysql驱动吧? 跟我这个主题有啥关系? 汗….

发表评论

邮箱地址不会被公开。 必填项已用*标注