MySQL主从复制的几种方案
数据库读写分离对于大型系统或者访问量很高的互联网应用来说,是必不可少的一个重要功能。 从数据库的角度来说,对于大多数应用来说,从集中到分布,最基本的一个需求不是数据存储的瓶颈,而是在于计算的瓶颈,即SQL查询的瓶颈,我们知道,正常情况下,Insert SQL就是几十个毫秒的时间内写入完成,而系统中的大多数Select SQL则要几秒到几分钟才能有结果,很多复杂的SQL,其消耗服务器CPU的能力超强,不亚于死循环的威力。在没有读写分离的系统上,很可能高峰时段的一些复杂SQL查询就导致数据库服务器CPU爆表,系统陷入瘫痪,严重情况下可能导致数据库崩溃。因此,从保护数据库的角度来说,我们应该尽量避免没有主从复制机制的单节点数据库。
对于MySQL来说,标准的读写分离是主从模式,一个写节点Master后面跟着多个读节点,读节点的数量取决于系统的压力,通常是1-3个读节点的配置,如下图所示:
MySQL支持更多的主从复制的拓扑关系,如下图所示,但通常我们不会采用双向主从同步以及环状的拓扑:
MySQL主从复制的原理如下:
第一步是在主库上记录二进制日志(稍后介绍如何设置)。在每次准备提交事务完成数 据更新前,主库将数据更新的事件记录到二进制日志中。MySQL会按事务提交的顺序 而非每条语句的执行顺序来记录二进制日志。在记录二进制日志后,主库会告诉存储引 擎可以提交事务了。 下一步,备库将主库的二进制日志复制到其本地的中继日志中。首先,备库会启动一个 工作线程,称为I/O线程,I/O线程跟主库建立一个普通的客户端连接,然后在主库上启 动一个特殊的二进制转储(binhg dump、线程(该线程没有对应的SQL命令),这个二 进制转储线程会读取主库上二进制日志中的事件。它不会对事件进行轮询。如果该线程 追赶上了主库,它将进入睡眠状态,直到主库发送信号量通知其有新的事件产生时才会 被唤醒,备库I/O线程会将接收到的事件记录到中继日志中。
备库的SQL线程执行最后一步,该线程从中继日志中读取事件并在备库执行,从而实现 备库数据的更新。当SQL线程追赶上I/O线程时,中继日志通常已经在系统缓存中,所 以中继日志的开销很低。SQL线程执行的事件也可以通过配置选项来决定是否写入其自 己的二进制日志中,它对于我们稍后提到的场景非常有用。这种复制架构实现了获取事件和重放事件的解耦,允许这两个过程异步进行。也就是说 I/o线程能够独立于SQL线程之外工作。但这种架构也限制了复制的过程,其中最重要 的一点是在主库上并发运行的査询在备库只能串行化执行,因为只有一个SQL线程来重 放中继日志中的事件。后面我们将会看到,这是很多工作负载的性能瓶颈所在。虽然有 一些针对该问题的解决方案,但大多数用户仍然受制于单线程。MySQL5.6以后,提供了基于GTID多开启多线程同步复制的方案,即每个库有一个单独的(sql thread)
进行同步复制,这将大大改善MySQL主从同步的数据延迟问题,配合Mycat分片,可以更好的将一个超级大表的数据同步的时延降低到最低。此外,用GTID避免了在传送 binlog 逻辑上依赖文件名和物理偏移量,能够更好的支持自动容灾切换,对运维人员来说应该是一件令人高兴的事情,因为传统的方式里,你需要找到binlog和POS点,然后change master to指向,而不是很有经验的运维,往往会将其找错,造成主从同步复制报错,在mysql5.6里,无须再知道binlog和POS点,需要知道master的IP、端口,账号密码即可,因为同步复制是自动的,mysql通过内部机制GTID自动找点同步。
即使是并发复制机制、仍然无法避免主从数据库的数据瞬间不同步的问题,因此又有了一种增强的方案,即galera for mysql、percona-cluster或者mariadb cluster等集群机制,他们是一种多主同步复制的模式,可以在任意节点上进行读写、自动控制成员,自动删除故障节点、自动加入节点、真正给予行级别的并发复制等强大能力!
下图是其原理图,通常是采用3个MySQL节点作为一个Cluster,即提供了3倍的数据库读的并发能力.galera for mysql集群这种方式,是牺牲了数据的写入速度,以换取最大程度的数据并发访问能力,类似Mycat里的全局表,并且保证了数据同时存在几个有效的副本,从而具有非常高的可靠性,因此在某种程度上,可以替代Oracle的一些关键场景,**目前开源中间件中,只有Mycat很完美的支持了galera for mysql集群模式。