在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如滴滴、阿里、汽车之家、极兔、有赞、希音、百度、网易、滴滴的面试资格,遇到一几个很重要的主从同步面试题:
- 说说MySQL主从同步的流程
- 说说MySQL主从同步的几种方式
- 说说MySQL主从数据同步机制
主从同步的重要性:
所以,这里尼恩给大家做一下系统化、体系化的梳理,使得大家可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”。
也一并把这个题目以及参考答案,收入咱们的 《尼恩Java面试宝典》V109版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。
注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请从公众号 【技术自由圈】获取。
当客户端提交一个事务到 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
)的从库追赶上主库,才能恢复为半同步复制。如果在此期间主库崩溃,仍然存在数据丢失的风险。
主从同步相关面试题,是非常常见的面试题。
以上的内容,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。
在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,并且在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。
最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。
《百亿级访问量,如何做缓存架构设计》
《多级缓存 架构设计》
《消息推送 架构设计》
《阿里2面:你们部署多少节点?1000W并发,当如何部署?》
《美团2面:5个9高可用99.999%,如何实现?》
《网易一面:单节点2000Wtps,Kafka怎么做的?》
《字节一面:事务补偿和事务重试,关系是什么?》
《网易一面:25Wqps高吞吐写Mysql,100W数据4秒写完,如何实现?》
《亿级短视频,如何架构?》
《炸裂,靠“吹牛”过京东一面,月薪40K》
《太猛了,靠“吹牛”过顺丰一面,月薪30K》
《炸裂了…京东一面索命40问,过了就50W+》
《问麻了…阿里一面索命27问,过了就60W+》
《百度狂问3小时,大厂offer到手,小伙真狠!》
《饿了么太狠:面个高级Java,抖这多硬活、狠活》
《字节狂问一小时,小伙offer到手,太狠了!》
《收个滴滴Offer:从小伙三面经历,看看需要学点啥?》
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓