说在前面
在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如滴滴、阿里、汽车之家、极兔、有赞、希音、百度、网易、滴滴的面试资格,遇到一几个很重要的主从同步面试题:
- 说说MySQL主从同步的流程
- 说说MySQL主从同步的几种方式
- 说说MySQL主从数据同步机制
主从同步的重要性:
- 解决数据可靠性的问题需要用到主从同步;
- 解决 MySQL 服务高可用要用到主从同步;
- 应对高并发的时候,还是要用到主从同步。
所以,这里尼恩给大家做一下系统化、体系化的梳理,使得大家可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”。
也一并把这个题目以及参考答案,收入咱们的 《尼恩Java面试宝典》V109版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。
注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请从公众号 【技术自由圈】获取。
文章目录
- 说在前面
- 一、MySQL 主从同步流程
- 二、主从同步的三种方式
- 1、异步复制
- 2、同步复制
- 3、半同步复制
- 三、半同步复制的注意问题
- 说在最后
- 推荐阅读
一、MySQL 主从同步流程
当客户端提交一个事务到 MySQL 的集群,直到客户端收到集群返回成功响应,在这个过程中,MySQL 集群需要执行很多操作:
- 主库需要:
- 提交事务
- 更新存储引擎中的数据
- 把 Binlog 写到磁盘上
- 给客户端返回响应
- 把 Binlog 复制到所有从库上
- 每个从库需要
- 把复制过来的 Binlog 写到暂存日志中
- 回放这个 Binlog
- 更新存储引擎中的数据
- 给主库返回复制成功的响应
这些操作的时序非常重要,这里面的时序,说的就是这些操作的先后顺序。同样的操作,因为时序不同,对应用程序来说,有很大的差异。
比如说,如果先复制 Binlog,等 Binlog 复制到从节点上之后,主节点再去提交事务,这种情况下,从节点的 Binlog 一直和主节点是同步的,任何情况下主节点宕机也不会丢数据。
然而,若将时序颠倒,先提交事务再复制 Binlog,性能将大幅提升,但数据丢失的风险也会增加。
MySQL 提供了几个参数来配置这个时序,我们先看一下默认情况下的时序是什么样的。
二、主从同步的三种方式
1、异步复制
默认情况下,MySQL 采用异步复制的方式,执行事务操作的线程不会等复制 Binlog 的线程。
在客户端向 MySQL 主库提交事务请求后,主库会先将事务记录到 Binlog,然后提交事务,更新存储引擎的数据,事务提交成功后,返回成功响应给客户端。
同时,从库会开启一个专门的复制线程,接收主库的 Binlog,并将其写入中继日志,然后向主库返回复制成功的响应。
此外,从库还有一个回放 Binlog 的线程,用于读取中继日志并回放 Binlog 以更新存储引擎的数据,这个过程与我们今天讨论的主从复制关系无关,因此在图中没有展示。
提交事务和复制这两个流程在不同的线程中独立执行,互不等待,这就是异步复制。
理解了异步复制的顺序后,我们就能更容易地理解之前几节课中提到的一些问题的原因。
例如,在异步复制下,为什么主库宕机会有数据丢失的风险?为什么读写分离会有读到脏数据的问题?
这些问题的产生,都是因为异步复制无法保证数据能第一时间复制到从库上。
异步复制的优点是性能优越,但缺点是数据安全性较差。在某一时刻,主从之间的数据差异可能较大,如果主机崩溃,从机接管时可能会丢失一部分数据。
2、同步复制
全同步复制跟半同步复制的区别是,全同步复制必须收到所有从库的ack,才会提交事务。
同步复制这种方式在实际项目中,基本上没法用,原因有两个:
- 一是性能很差,因为要复制到所有节点才返回响应;
- 二是可用性也很差,主库和所有从库任何一个数据库出问题,都会影响业务。
全同步复制的数据一致性最好,但是性能也是最差的。
3、半同步复制
为了解决这个问题,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,请到下面公号【技术自由圈】取↓↓↓