关于主从延迟,一篇文章给你讲明白了

生活中所受的苦,终会以一种形式回归!

前言

在实际的生产环境中,由单台MySQL作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面

因此,一般来说都是通过集群主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力进行部署与实施

总结MySQL主从集群带来的作用是:

提高数据库负载能力,主库执行读写任务(增删改),备库仅做查询。提高系统读写性能、可扩展性和高可用性。数据备份与容灾,备库在异地,主库不存在了,备库可以立即接管,无须恢复时间。

说到主从同步,离不开binlog这个东西,先介绍下binlog吧

biglog

binlog是什么?有什么作用?

用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。可以简单理解为记录的就是sql语句

binlog是mysql的逻辑日志,并且由Server层进行记录,使用任何存储引擎的mysql数据库都会记录binlog日志

在实际应用中,binlog的主要使用场景有两个:

用于主从复制,在主从结构中,binlog作为操作记录从master被发送到slave,slave服务器从master接收到的日志保存到relaylog中。

用于数据备份,在数据库备份文件生成后,binlog保存了数据库备份后的详细信息,以便下一次备份能从备份点开始。

日志格式

binlog日志有三种格式,分别为STATMENT、ROW和MIXED

在MySQL5.7.7之前,默认的格式是STATEMENT,MySQL5.7.7之后,默认值是ROW

日志格式通过binlog-format指定。

STATMENT:基于SQL语句的复制,每一条会修改数据的sql语句会记录到binlog中ROW:基于行的复制MIXED:基于STATMENT和ROW两种模式的混合复制,比如一般的数据操作使用row格式保存,有些表结构的变更语句,使用statement来记录

我们还可以通过mysql提供的查看工具mysqlbinlog查看文件中的内容,例如

mysqlbinlogmysql-bin.

more

binlog文件大小和个数会不断的增加,后缀名会按序号递增,例如mysql-bin.等。

主从复制原理

可以看到mysql主从复制需要三个线程:master(binlogdumpthread)、slave(I/Othread、SQLthread)

binlogdump线程:主库中有数据更新时,根据设置的binlog格式,将更新的事件类型写入到主库的binlog文件中,并创建logdump线程通知slave有数据更新。当I/O线程请求日志内容时,将此时的binlog名称和当前更新的位置同时传给slave的I/O线程。

I/O线程:该线程会连接到master,向logdump线程请求一份指定binlog文件位置的副本,并将请求回来的binlog存到本地的relaylog中。

SQL线程:该线程检测到relaylog有更新后,会读取并在本地做redo操作,将发生在主库的事件在本地重新执行一遍,来保证主从数据同步。

基本过程总结

主库写入数据并且生成binlog文件。该过程中MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。从库服务器上的IO线程连接Master服务器,请求从执行binlog日志文件中的指定位置开始读取binlog至从库。主库接收到从库的IO线程请求后,其上复制的IO线程会根据Slave的请求信息分批读取binlog文件然后返回给从库的IO线程。Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的RelayLog(即中继日志)文件的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容。从库服务器的SQL线程会实时监测到本地RelayLog中新增了日志内容,然后把RelayLog中的日志翻译成SQL并且按照顺序执行SQL来更新从库的数据。从库在relay-log.info中记录当前应用中继日志的文件名和位置点以便下一次数据复制。并行复制

在MySQL5.6版本之前,Slave服务器上有两个线程I/O线程和SQL线程。

I/O线程负责接收二进制日志,SQL线程进行回放二进制日志。如果在MySQL5.6版本开启并行复制功能,那么SQL线程就变为了coordinator线程,coordinator线程主要负责以前两部分的内容

上图的红色框框部分就是实现并行复制的关键所在

这意味着coordinator线程并不是仅将日志发送给worker线程,自己也可以回放日志,但是所有可以并行的操作交付由worker线程完成。

coordinator线程与worker是典型的生产者与消费者模型。

不过到MySQL5.7才可称为真正的并行复制,这其中最为主要的原因就是slave服务器的回放与主机是一致的即master服务器上是怎么并行执行的slave上就怎样进行并行回放。不再有库的并行复制限制,对于二进制日志格式也无特殊的要求。

为了兼容MySQL5.6基于库的并行复制,5.7引入了新的变量slave-parallel-type,其可以配置的值有:

DATABASE:默认值,基于库的并行复制方式LOGICAL_CLOCK:基于组提交的并行复制方式

下面分别介绍下两种并行复制方式

按库并行

每个worker线程对应一个hash表,用于保存当前正在这个worker的执行队列里的事务所涉及到的库。其中hash表里的key是数据库名,用于决定分发策略。该策略的优点是构建hash值快,只需要库名,同时对于binlog的格式没有要求。

但这个策略的效果,只有在主库上存在多个DB,且各个DB的压力均衡的情况下,这个策略效果好。因此,对于主库上的表都放在同一个DB或者不同DB的热点不同,则起不到多大效果

组提交优化

该特性如下:

能够同一组里提交的事务,定不会修改同一行;

主库上可以并行执行的事务,从库上也一定可以并行执行。

具体是如何实现的:

在同一组里面一起提交的事务,会有一个相同的


转载请注明:http://www.aierlanlan.com/cyrz/3028.html