来源:技术自由圈
最近有小伙伴拿到了一线互联网企业如滴滴、阿里、汽车之家、极兔、有赞、希音、百度、网易、滴滴的面试资格,遇到一几个很重要的面试题:
说说MySQL主从同步的流程 说说MySQL主从同步的几种方式
主从同步的重要性:
所以,这里给大家做一下系统化、体系化的梳理,使得大家可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”。
- 说在前面
- 一、MySQL 主从同步流程
- 二、主从同步的三种方式
- 1、异步复制
- 2、同步复制
- 3、半同步复制
- 三、半同步复制的注意问题
- 说在最后
- 部分历史案例
当客户端提交一个事务到 MySQL 的集群,直到客户端收到集群返回成功响应,在这个过程中,MySQL 集群需要执行很多操作:
注意:请点击图像以查看清晰的视图!
这些操作的时序非常重要,这里面的时序,说的就是这些操作的先后顺序。同样的操作,因为时序不同,对应用程序来说,有很大的差异。
比如说,如果先复制 Binlog,等 Binlog 复制到从节点上之后,主节点再去提交事务,这种情况下,从节点的 Binlog 一直和主节点是同步的,任何情况下主节点宕机也不会丢数据。
然而,若将时序颠倒,先提交事务再复制 Binlog,性能将大幅提升,但数据丢失的风险也会增加。
MySQL 提供了几个参数来配置这个时序,我们先看一下默认情况下的时序是什么样的。
默认情况下,MySQL 采用异步复制的方式,执行事务操作的线程不会等复制 Binlog 的线程。
注意:请点击图像以查看清晰的视图!
在客户端向 MySQL 主库提交事务请求后,主库会先将事务记录到 Binlog,然后提交事务,更新存储引擎的数据,事务提交成功后,返回成功响应给客户端。
同时,从库会开启一个专门的复制线程,接收主库的 Binlog,并将其写入中继日志,然后向主库返回复制成功的响应。
此外,从库还有一个回放 Binlog 的线程,用于读取中继日志并回放 Binlog 以更新存储引擎的数据,这个过程与我们今天讨论的主从复制关系无关,因此在图中没有展示。
提交事务和复制这两个流程在不同的线程中独立执行,互不等待,这就是异步复制。
理解了异步复制的顺序后,我们就能更容易地理解之前几节课中提到的一些问题的原因。
例如,在异步复制下,为什么主库宕机会有数据丢失的风险?为什么读写分离会有读到脏数据的问题?
这些问题的产生,都是因为异步复制无法保证数据能第一时间复制到从库上。
异步复制的优点是性能优越,但缺点是数据安全性较差。在某一时刻,主从之间的数据差异可能较大,如果主机崩溃,从机接管时可能会丢失一部分数据。
全同步复制跟半同步复制的区别是,全同步复制必须收到所有从库的ack,才会提交事务。
同步复制这种方式在实际项目中,基本上没法用,原因有两个:
全同步复制的数据一致性最好,但是性能也是最差的。
为了解决这个问题,MySQL 从 5.7 版本开始,增加一种 半同步复制(Semisynchronous Replication)的方式。
在 master 更新操作写入 Binlog 后,会主动通知 slave,slave 接收到后写入 Relay Log 即可回应。master 只需收到至少一个 ACK 应答,便可提交事务。
可以发现,相较于异步复制,半同步复制需要至少一个 slave 将 Binlog 写入 Relay Log,这在一定程度上降低了性能,但能够确保至少有一个从库与 master 的数据保持一致,从而提高数据安全性。
注意:请点击图像以查看清晰的视图!
半同步复制兼顾了异步复制和同步复制的优点。如果主库宕机,至少还有一个从库拥有最新数据,不会出现数据丢失的风险。
并且,半同步复制的性能也还凑合,也能提供高可用保证,从库宕机也不会影响主库提供服务。因此,这种折衷的复制方式半同步复制,也是一种不错的选择。
接下来,将向大家介绍,在实际应用中选择半同步复制时需要特别关注的几个问题。
在配置半同步复制时,有一个关键参数 rpl_semi_sync_master_wait_no_slave
,其含义是:「等待至少几个从节点完成数据复制后再返回」。
该参数设置的值越大,数据丢失的风险越小,但集群的性能和可用性会相应降低。最大值可以设置为与从节点数量相同,这样就变成了同步复制。
通常情况下,使用默认值 1 即可,这样可以最大程度地减小性能损失,同时保证高可用性。只要还有一个从库正常运行,就不会影响主库的读写操作。数据丢失的风险也较小,除非主库和拥有最新数据的从库同时出现问题,才有可能发生数据丢失。
另一个重要的参数是 rpl_semi_sync_master_wait_point
,它控制主库执行事务的线程是在提交事务之前(AFTER_SYNC)等待复制,还是在提交事务之后(AFTER_COMMIT)等待复制。默认值为 AFTER_SYNC,即先等待复制,再提交事务,这样可以确保不丢失任何数据。AFTER_COMMIT 具有更好的性能,不会长时间锁定表,但仍然存在因主机崩溃而导致数据丢失的风险。
此外,尽管我们设置了同步或半同步复制,并等待复制成功后再提交事务,但仍然存在一种容易被忽视、可能引发数据丢失风险的情况。
如果主库提交事务的线程等待复制的时间超过设定的阈值,事务仍然会被正常提交。此外,MySQL 会自动降级为异步复制模式,直到有足够多(rpl_semi_sync_master_wait_no_slave
)的从库追赶上主库,才能恢复为半同步复制。如果在此期间主库崩溃,仍然存在数据丢失的风险。
转载声明:所有转载文章必注明原文出处或转载出处(转载处未注明原文出处的情况),如有侵权请联系删除