主从复制原理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了主从复制原理相关的知识,希望对你有一定的参考价值。

参考技术A Redis的主从同步分为:    完整重同步(full resynchronization)
                                          部分重同步(partial resynchronization)

有两种情况下是完整重同步:
                                slave连接上master第一次复制的时候;
                                如果当主从断线,重新连接复制的时候有可能是完整重同步

1.从服务器连接主服务器,发送SYNC命令
2.主服务器接收到SYNC命名后,开始执行bgsave命令生成RDB文件并使用缓冲区记录此后执行的所有写命令
3.主服务器basave执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令
4.从服务器收到快照文件后丢弃所有旧数据,载入收到的快照
5.主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令
6.从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令

 用于处理断线后重复制的情况,先介绍几个用于部分重同步的部分

runid(replication ID),主服务器运行id,Redis实例在启动时,随机生成一个长度40的唯一字符串来标识当前节点
offset,复制偏移量。主服务器和从服务器各自维护一个复制偏移量,记录传输的字节数。当主节点向从节点发送N个字节数据时,主节点的offset增加N,从节点收到主节点传来的N个字节数据时,从节点的offset增加N
replication backlog buffer,复制积压缓冲区。是一个固定长度的FIFO队列,大小由配置参数repl-backlog-size指定,默认大小1MB。需要注意的是该缓冲区由master维护并且有且只有一个,所有slave共享此缓冲区,其作用在于备份最近主库发送给从库的数据

当slave连接到master,会执行PSYNC <runid> <offset>发送记录旧的master的runid(replication ID)和偏移量offset,这样master能够只发送slave所缺的增量部分。但是如果master的复制积压缓存区没有足够的命令记录,或者slave传的runid(replication ID)不对,就会进行完整重同步,即slave会获得一个完整的数据集副本

当slave断开重连后,会发送psync 命令给master。

master首先会对服务器运行进行判断,如果与自己相同就进行判断偏移量

master会判断自己的偏移量与slave的偏移量是否一致。

如果不一致,master会去缓冲区中判断slave的偏移量之后的数据是否存在。

如果存在就会返回+continue回复,表示slave可以执行部分同步了。

master发送断线后的写命令给slave

slave执行写命令

PSYNC命令执行完整重同步和部分重同步的流程图

命令传播

当完成数据同步之后,主从服务器的数据暂时达到一致状态,当主服务器执行了客户端的写命令之后,主从的数据便不再一致。为了能够使主从服务器的数据保持一致性,主服务器会对从服务器执行命令传播操作,即 每执行一个写命令就会向从服务器发送同样的写命令

在命令传播阶段,从服务器会默认以每秒一次的频率向主服务器发送心跳检测REPLCONF ACK <replication_offset>其中replication_offset是当前从服务器的复制偏移量,该命令的作用有三个

检测主从服务器的网络连接状态
辅助实现min-slaves选项
检测命令丢失

https://baijiahao.baidu.com/s?id=1644916874411447363&wfr=spider&for=pc

MySQL主从复制原理

MySQL的复制及各种高可用架构,基本都是基于主从复制的组合。而主从复制是基于binary log的,

这里就详细介绍下基于binary log event(二进制日志事件)复制的原理。

主从复制有实现两种方法:传统复制方式(基于server_id)和GTID(全局事务ID).(MySQL5.6以后支持)

 二、原理详解

1.简单来说(三个线程三个步骤):

1)主服务器Master将数据库的改变写入二进制日志文件,并维护一个等待从服务器连接的线程binlog_dump;

2)从服务器Slave会启动一个线程(IO Thread)和主服务器Master的binlog_dump线程建立连接,然后将数据

读取到从服务器Slave,并写入中继日志(Relay log);

3)从服务器Slave另一个线程(SQL thread)会从中继日志中读取数据,并在从数据库应用更新,完成数据同步。

2.细节实现:

  MySQL使用3个线程来执行复制功能(一个在主服务器,两个在从服务器)。

1)当从服务器发出start slave时,从服务器Slave创建一个I/0线程,去连接主服务器Master并让他发送记录在其二进制日志中的语句。

2)主服务器Master创建一个线程Binlog Dump将二进制日志中的内容发送到从服务器Slave。(可在show processlist中看到该线程)

3)从服务器Slave I/O线程读取主服务器Binlog Dump线程发送过来的内容并将数据拷贝到从服务器数据目录中的中继日志中Relay log。

4)从服务器Slave创建SQL线程,用于读取中继日志并执行日志中包含的更新。

在从服务器上读取和执行更新语句被分成两个独立的任务,当从服务器启动时,其I/O线程可以很快地从主服务器Master索取所有

二进制日志内容,同时交由SQL线程来更新应用到从库(会有点慢)。

3.复制线程的状态

  通过show processlist可以看到三个线程的状态,show slave status 可以看到IO、SQL线程的状态。常见的状态有:

1)主服务器Binlog Dump线程状态:

Master has sent all binlog to slave; waiting for binlog to be updated

线程已经从二进制日志中读取所有主要的更新并已经发送到从服务器。

线程现在正空闲,等待由主服务器上新的更新导致的出现在二进制日志文件中新的事务。

 

2)从服务器I/O线程状态:

Waiting for master to send event

线程已经连接上主服务器,正在等待二进制日志事件到达。如果主服务器正空闲,会持续较长时间。

如果等待持续slave_net_timeout秒,则发生超时。此时,线程认为连接中断并企图重新连接。

 

3)从服务器SQL线程状态:

Reading event from the relay log

线程已经从中继日志中读取一个事件,可以对事件进行处理了。

Slave has read all relay log;waiting for the slave I/O thread to update it

线程已经处理了中继日志文件中的所有事件,现在正在等待I/O线程将新事件写入中继日志。

 

4.复制过程中状态的保持:

  从服务器通过在my.cnf设置如下参数,将主从状态保存在mysql库的表中slave_master_info、slave_relay_log_info。

下次从服务器启动时,读取这个表来确定它已经从主服务器读取了多少二进制日志,已经自己处理装机日志的程度。

relay_log_info_repository = TABLE
master_info_repository = TABLE

以上是关于主从复制原理的主要内容,如果未能解决你的问题,请参考以下文章

MySQL的主从复制原理以及流程

主从复制--01---主从复制的原理搭建

MySQL 运维 主从复制 -- 主从复制概述主从复制原理搭建MySQL主从复制

深度探索MySQL主从复制原理

MySQL主从复制+读写分离原理及配置实例

[MySQL] 主从复制原理