什么是复制
https://dev.mysql.com/doc/refman/8.0/en/replication.html
MySQL Replication是官方提供的主从同步方案,也是用的最广的同步方案。Replication(复制)使来自一个MySQL数据库服务器(称为源(Source))的数据能够复制到一个或多个MySQL服务器(称为副本(Replica))。默认情况下,复制是异步的;副本不需要永久连接即可从源接收更新。根据配置,用户可以复制所有数据库、指定数据库,甚至某个数据库中的指定表。
说明:旧版本的 MySQL复制将源(Source)称为主(Master),将副本(Replica)称为从(Slave)

主从复制的优势:
- 高可用:通过配置一定的复制机制,MySQL实现了跨主机的数据复制,从而获得一定的高可用能力,如果需要获得更高的可用性,只需要配置多个副本,或者进行级联复制就可以达到目的。
- 性能扩展:由于复制机制提供了多个数据备份,可以通过配置一个或多个副本,将读请求分发至副本节点,从而获得整体上读写性能的提升。
- 异地灾备:只需要将副本节点部署到异地机房,就可以轻松获得一定的异地灾备能力。实际当中,需要考虑网络延迟等可能影响整体表现的因素。
- 交易分离:通过配置复制机制,并将低频、大运算量的交易发送至副本节点执行,就可以避免这些交易与高频交易竞争运算资源,从而避免整体的性能问题。
主从复制的缺点:
- 没有故障自动转移,容易造成单点故障
- 主库从库之间有主从复制延迟问题,容易造成最终数据的不一致
- 从库过多对主库的负载以及网络带宽都会带来很大的负担
应用场景
- 电子商务平台:在电商平台中,主从复制可以用于实现读写分离,提高并发处理能力,同时确保数据的一致性。
- 社交网络:在社交网络应用中,可以利用主从复制来提供快速的读取服务,同时将数据变更复制到从数据库以备份数据。
- 实时监控和报警系统:在监控系统中,主从复制可以用于实现数据的分布式存储和快速数据查询。
- 新闻和媒体网站:在高访问量的新闻网站中,可以使用主从复制来提供高可用性和快速的内容访问。
- 金融服务:在金融行业,数据的安全性和可用性至关重要,主从复制可以用于数据备份和高可用性的实现。
复制的方式分类
MySQL8.0支持多种复制方式:
传统的方法是基于从源的二进制日志(binlog)复制事件,并要求日志文件及其中的位置在源和副本之间进行同步。作为源 (数据库更改发生的地方)的MySQL实例将更新和更改作为"事件"写入二进制日志。根据所记录的数据库更改,二进制日志中的信息以不同的日志格式存储。副本配置为从源中读取 二进制日志,并在副本的本地数据库上执行二进制日志中的事件。
#获取binlog文件列表
mysql> show binary logs;
#查看指定binlog文件的内容
mysql> show binlog events in 'binlog.000003';
https://dev.mysql.com/doc/refman/8.0/en/binlog-replication-configuration-overview.html
基于全局事务标识符(GTID)的方式。基于GTID的复制是完全基于事务的,所以很容易确定源和副本是否一致;只要在源上提交的所有事务也在副本上提交,就可以保证两者之间的一致性。
https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html
复制的数据同步类型
MySQL中的复制支持不同类型的同步。同步的原始类型是单向异步复制,其中一个服务器充当源,而一个或多个其他服务器充当副本。在MySQL8.0中,除了内置的异步复制之外,还支持半同步复制。使用半同步复制,在返回执行事务的会话之前,对源执行提交,直到至少有一个副本确认它已经接收并记录了事务的事件。MySQL8.0还支持延迟复制,以使副本故意落后于源至少指定的时间。
异步复制
默认情况下,MySQL采用异步复制的方式,执行事务操作的线程不会等复制Binlog的线程。具体的时序见下图:

MySQL主库在收到客户端提交事务的请求之后,会先写入Binlog,然后再提交事务,更新存储引擎中的数据,事务提交完成后,给客户端返回操作成功的响应。同时,从库会有一个专门的复制线程,从主库接收Binlog,然后把Binlog写到一个中继日志里面,再给主库返回复制成功的响应。从库还有另外一个回放Binlog的线程,去读中继日志,然后回放Binlog更新存储引擎中的数据。
提交事务和复制这两个流程在不同的线程中执行,互相不会等待,这是异步复制。异步复制的劣势是,可能存在主从延迟,如果主节点宕机,可能会丢数据。
半同步复制
MySQL 从5.7版本开始,增加一种半同步复制(Semisynchronous Replication) 的方式。这种机制与异步复制相比主要有如下区别:
- 主节点在收到客户端的请求后,必须在完成本节点日志写入的同时,还需要等待至少一个从节点完成数据同步的响应之后(或超时),才会响应请求。
- 从节点只有在写入relay-log并完成刷盘之后,才会向主节点响应。
- 当从节点响应超时时,主节点会将同步机制退化为异步复制。在至少一个从节点恢复,并完成数据追赶后,主节点会将同步机制恢复为半同步复制。

可以看出,相比于异步复制,半同步复制在一定程度上提高了数据的可用性,在未退化至异步复制时,如果主节点宕机,此时数据已复制至至少一台从节点。同时,由于向客户端响应时需要从节点完成响应,相比于异步复制,此时多出了主从节点上网络交互的耗时以及从节点写文件并刷盘的耗时,因此整体上集群对于客户端的响应性能表现必然有所降低。
半同步复制有两个重要的参数:
- rpl semi sync master wait slave count (8.0.26后为rpl semi sync source wait for replica count) :至少等待数据复制到几个从节点再返回。这个数量配置的越大,去数据的风险越小,但是集群的性能和可用性就越差。
- rpL_semi_sync_master _wait point (8.0.26之后改为rp sem_sync_source_wait_point) :这个参数控制主库执行事务的线程,是在提交事务之前(AFTER_SYNC)等待复制,还是在提交事务之后(AFTER_COMMIT)等待复制。默认是AFTER_SYNC,也就是先等待复制,再提交事务,这样就不会丢数据。
复制的设计理念
复制状态机--几乎所有的分布式存储都是这么复制数据的
在MySQL中,无论是复制还是备份恢复,依赖的都是全量备份和Binlog,全量备份相当于备份那一时刻的一个数据快照,Binlog则记录了每次数据更新的变化,也就是操作日志。这种基于"快照+操作日志"的方法,不是MySQL特有的。比如说,RedisCluster中,它的全量备份称为 Snapshot,操作日志叫 backlog,它的主从复制方式几乎和 MySQL是一模一样的。Elasticsearch用的是translog,它备份和恢复数据的原理和实现方式也是完全一样的。
任何一个存储系统,无论它存储的是什么数据,用什么样的数据结构,都可以抽象成一个状态机。存储系统中的数据称为状态(也就是MySQL中的数据),状态的全量备份称为快照(Snapshot,就像给数据拍个照片一样。我们按照顺序记录更新存储系统的每条操作命令,就是操作日志(Commit Log,也就是MySQL中的Binlog)。

复制数据的时候,只要基于一个快照,按照顺序执行快照之后的所有操作日志,就可以得到一个完全一样的状态。在从节点持续地从主节点上复制操作日志并执行,就可以让从节点上的状态数据和主节点保持同步。
主从同步做数据复制时,一般可以采用几种复制策略。
- 性能最好的方法是异步复制,主节点上先记录操作日志,再更新状态数据,然后异步把操作日志复制到所有从节点上,并在从节点执行操作日志,得到和主节点相同的状态数据。异步复制的劣势是,可能存在主从延迟,如果主节点宕机,可能会去数据。
- 另外一种常用的策略是半同步复制,主节点等待操作日志最少成功复制到N个从节点上之后,再更新状态,这种方式在性能、高可用和数据可靠性几个方面都比较平衡,很多分布式存储系统默认采用的都是这种方式。
基于binlog位点同步的主从复制原理

1、主库会生成多个binlog日志文件。
2、从库的IO线程请求指定文件和指定位置的binlog日志文件(位点)。
3、主库dump线程获取指定位点的binlog日志。
4、主库按照从库发送给来的位点信息读取binlog,然后推送binlog给从库。
5、从库将得到的binlog写到本地的relay log(中继日志)文件中。
6、从库的SQL线程读取和解析relay log文件。
7、从库的SQL线程重放relaylog中的命令。