MySQL 中的集群部署方案
前言
这里来聊聊,MySQL 中常用的部署方案。
MySQL Replication
MySQL Replication
是官方提供的主从同步方案,用于将一个 MySQL 的实例同步到另一个实例中。Replication 为保证数据安全做了重要的保证,是目前运用最广的 MySQL 容灾方案。Replication 用两个或以上的实例搭建了 MySQL 主从复制集群,提供单点写入,多点读取的服务,实现了读的 scale out
。
上面的栗子,一个主库(M),三个从库(S),通过 replication,Master 生成 event 的 binlog,然后发给 slave,Slave 将 event 写入 relaylog,然后将其提交到自身数据库中,实现主从数据同步。
对于数据库之上的业务层来说,基于 MySQL 的主从复制集群,单点写入 Master ,在 event 同步到 Slave 后,读逻辑可以从任何一个 Slave 读取数据,以读写分离的方式,大大降低 Master 的运行负载,同时提升了 Slave 的资源利用。
优点:
1、通过读写分离实现横向扩展的能力,写入和更新操作在源服务器上进行,从服务器中进行数据的读取操作,通过增大从服务器的个数,能够极大的增强数据库的读取能力;
2、数据安全,因为副本可以暂停复制过程,所以可以在副本上运行备份服务而不会破坏相应的源数据;
3、方便进行数据分析,可以在写库中创建实时数据,数据的分析操作在从库中进行,不会影响到源数据库的性能;
实现原理
在主从复制中,从库利用主库上的 binlog 进行重播,实现主从同步,复制的过程中蛀主要使用到了 dump thread,I/O thread,sql thread
这三个线程。
IO thread
: 在从库执行 start slave
语句时创建,负责连接主库,请求 binlog,接收 binlog 并写入 relay-log;
dump thread
:用于主库同步 binlog 给从库,负责响应从 IO thread
的请求。主库会给每个从库的连接创建一个 dump thread
,然后同步 binlog 给从库;
sql thread
:读取 relay log
执行命令实现从库数据的更新。
来看下复制的流程:
1、主库收到更新命令,执行更新操作,生成 binlog;
2、从库在主从之间建立长连接;
3、主库 dump_thread 从本地读取 binlog 传送刚给从库;
4、从库从主库获取到 binlog 后存储到本地,成为 relay log
(中继日志);
5、sql_thread 线程读取 relay log
解析、执行命令更新数据。
不过 MySQL Replication
有个严重的缺点就是主从同步延迟。
因为数据是进行主从同步的,那么就会遇到主从同步延迟的情况。
为什么会出现主从延迟?
1、从库机器的性能比主库差;
2、从库的压力大;
- 大量查询放在从库上,可能会导致从库上耗费了大量的 CPU 资源,进而影响了同步速度,造成主从延迟。
3、大事务的执行;
- 有事务产生的时候,主库必须要等待事务完成之后才能写入到 binlog,假定执行的事务是一个非常大的数据插入,这些数据传输到从库,从库同步这些数据也需要一定的时间,就会导致从节点出现数据延迟。
4、从库的复制能力较差;
如果从库的复制能力,低于主库,那么在主库写入压力很大的情况下,就会造成从库长时间数据延迟的情况出现。
如何解决?
1、优化业务逻辑,避免出现多线程大事务的并发场景;
2、提高从库的机器性能,减少主库写 binlog 和从库读 binlog 的效率差;
3、保证主库和从库的网络连接,避免出现网络延迟导致的 binlog 传输延迟;
4、强行读主库;
5、配合 semi-sync 半同步复制;
semi-sync 半同步复制
MySQL 有三种同步模式,分别是:
1、异步复制:MySQL 中默认的复制是异步的,主库在执行完客户端提交的事务后会立即将结果返回给客户端,并不关心从库是否已经接收并且处理。存在问题就是,如果主库的日志没有及时同步到从库,然后主库宕机了,这时候执行故障转移,在从库冲选主,可能会存在选出的主库中数据不完整;
2、全同步复制:指当主库执行完一个事务,并且等到所有从库也执行完成这个事务的时候,主库在提交事务,并且返回数据给客户端。因为要等待所有从库都同步到主库中的数据才返回数据,所以能够保证主从数据的一致性,但是数据库的性能必然受到影响;
3、半同步复制:是介于全同步和全异步同步的一种,主库至少需要等待一个从库接收并写入到 Relay Log
文件即可,主库不需要等待所有从库给主库返回 ACK。主库收到 ACK ,标识这个事务完成,返回数据给客户端。
MySQL 中默认的复制是异步的,所以主库和从库的同步会存在一定的延迟,更重要的是异步复制还可能引起数据的丢失。全同步复制的性能又太差了,所以从 MySQL 5.5
开始,MySQL 以插件的形式支持 semi-sync 半同步复制。
半同步复制潜在的问题
在传统的半同步复制中,主库写数据到 binlog,并且执行 commit 提交事务后,会一直等待一个从库的 ACK。从库会在写入 Relay Log
后,将数据落盘,然后回复给主库 ACK,主库收到这个 ACK 才能给客户端事务完成的确认。
这样会存在问题就是,主库已经将该事务的 commit 存储到了引擎层,应用已经可以看到数据的变化了,只是在等待从库的返回,如果此时主库宕机,可能从库还没有写入 Relay Log,就会发生主从库数据不一致。
为了解决这个问题,MySQL 5.7
引入了增强半同步复制。主库写入数据到 binlog 后,就开始等待从库的应答 ACK,直到至少一个从库写入 Relay Log
后,并将数据落盘,然后返回给主库 ACK,通知主库可以进行 commit 操作,然后主库再将事务提交到事务引擎,应用此时才能看到数据的变化。
不过看下来增强半同步复制,在同步给从库之后,因为自己的数据还没有提交,然后宕机了,主库中也是会存在数据的丢失,不过应该想到的是,这时候主库宕机了,是会重新在从库中选主的,这样新选出的主库数据是没有发生丢失的。
MySQL Group Replication
MySQL Group Replication
组复制,又称为 MGR。是 Oracle MySQL
于 2016 年 12 月发布 MySQL 5.7.17
推出的一个全新高可用和高扩展的解决方案。
引入复制组主要是为了解决传统异步复制和半同步复制可能产生数据不一致的问题。
MGR 由若干个节点共同组成一个复制组,一个事务的提交,必须经过组内大多数节点 (N / 2 + 1)
决议并通过,才能得以提交。</