MySQL主从相关

什么是复制

复制(Replication):
 MySQL Replication是官方提供的主从同步方案,也是用的最广的同步方案。Replication(复制)使来自一个MySQL数据库服务器(称为源(Source))的数据能够复制到一个或多个MySQL服务器(称为副本(Replica))。默认情况下,复制是异步的;副本不需要永久连接即可从源接收更新。根据配置,你可以复制所有数据库、指定数据库,甚至某个数据库中的指定表。


读写分离.png

 binlog还可进行数据迁移。

复制优势与缺陷

复制的优势:
 高可用:通过配置一定的复制机制,MySQL实现了跨主机的数据复制,从而获得一定的高可用能力,如果需要获得更高的可用性,只需要配置多个副本,或者进行级联复制就可以达到目的;
 性能扩展:由于复制机制提供了多个数据备份,可以通过配置一个或多个副本,将读请求分发至副本节点,从而获得整体上读写性能的提升;
 异地灾备:只需要将副本节点部署到异地机房,就可以轻松获得一定的异地灾备能力。实际当中,需要考虑网络延迟等可能影响整体表现的因素;
 交易分离:通过配置复制机制,并将低频、大运算量的交易发送至副本节点执行,就可以避免这些交易与高频交易竞争运算资源,从而避免整体的性能问题。

复制的缺陷:
 没有故障自动转移,容易造成单点故障;
 主库从库之间有主从复制延迟问题,容易造成最终数据的不一致;
 从库过多对主库的负载以及网络带宽都会带来很大的负担。

应用场景
  • 电子商务平台: 在电商平台中,主从复制可以用于实现读写分离,提高并发处理能力,同时确保数据的一致性。
  • 社交网络: 在社交网络应用中,可以利用主从复制来提供快速的读取服务,同时将数据变更复制到从数据库以备份数据。
  • 实时监控和报警系统: 在监控系统中,主从复制可以用于实现数据的分布式存储和快速数据查询。
  • 新闻和媒体网站: 在高访问量的新闻网站中,可以使用主从复制来提供高可用性和快速的内容访问。
  • 金融服务: 在金融行业,数据的安全性和可用性至关重要,主从复制可以用于数据备份和高可用性的实现。
MySQL 8.0支持多种复制方式:
  •  传统的方法是基于从源的二进制日志(binlog)复制事件,并要求日志文件及其中的位置在源和副本之间进行同步。作为源(数据库更改发生的地方)的MySQL实例将更新和更改作为"事件"写入二进制日志。根据所记录的数据库更改,二进制日志中的信息以不同的日志格式存储。副本配置为从源中读取二进制日志,并在副本的本地数据库上执行二进制日志中的事件。
  •  基于全局事务标识符(GTID)的方式。基于GTID的复制是完全基于事务的,所以很容易确定源和副本是否一致; 只要在源上提交的所有事务也在副本上提交,就可以保证两者之间的一致性。

 MySQL中的复制支持不同类型的同步。同步的原始类型是单向异步复制,其中一个服务器充当源,而一个或多个其他服务器充当副本。在 MySQL 8.0中,除了内置的异步复制之外,还支持半同步复制。使用半同步复制,在返回执行事务的会话之前,对源执行提交,直到至少有一个副本确认它已经接收并记录了事务的事件。MySQL 8.0还支持延迟复制,以使副本故意落后于源至少指定的时间。

从源的二进制日志复制事件(不支持自动故障转移)

异步复制

 默认情况下,MySQL采用异步复制的方式,执行事务操作的线程不会等复制binlog的线程。

异步复制.png

 MySQL主库在收到客户端提交事务的请求之后,会先写入binlog,然后再提交事务,更新存储引擎中的数据,事务提交完成后,给客户端返回操作成功的响应。同时,从库会有一个专门的复制线程,从主库接收binlog,然后把binlog写到一个中继日志里面,再给主库返回复制成功的响应。从库还有另外一个回放binlog的线程,去读中继日志,然后回放binlog更新存储引擎中的数据。(要求:从库响应之后,返回响应给主库,主库返回响应给客户端,主库可以不等待直接返回;效果:主库修改,从库同步修改,主库宕机,从库可能丢数据)
(MySQL 主库在收到客户端提交事务的请求之后,会先写入binlog,然后再提交事务,从主库接收binlog,写入中继日志返回给主库,但主库不会等待从库,直接就修改返回了)
 提交事务和复制这两个流程在不同的线程中执行,互相不会等待,这是异步复制。
 异步复制的劣势是,可能存在主从延迟,如果主节点宕机,可能会丢数据。

半同步复制

 MySQL从5.7版本开始,增加一种半同步复制(Semisynchronous Replication)的方式。这种机制与异步复制相比主要有如下区别:
 主节点在收到客户端的请求后(execute),必须在完成本节点日志写入的同时,还需要等待至少一个从节点完成数据同步的响应之后(或超时),才会响应请求。
 从节点只有在写入relay-log(中继日志)并完成刷盘之后,才会向主节点响应。
 当从节点响应超时时,主节点会将同步机制退化为异步复制。在至少一个从节点恢复,并完成数据追赶后,主节点会将同步机制恢复为半同步复制。
(MySQL 主库在收到客户端提交事务的请求之后,会先写入 binlog,传binlog日志,从库接收写入中继日志返回给主库,主库至少等待一个从库完成,从库宕机了会退化为异步复制;至少一个从节点恢复,并完成数据追赶后,会恢复为半同步复制。)

半同步复制.png

半同步复制有两个重要的参数:

  •  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之后改为rpl_semi_sync_source_wait_point):这个参数控制主库执行事务的线程,是在提交事务之前(AFTER_SYNC)等待复制,还是在提交事务之后(AFTER_COMMIT)等待复制。默认是AFTER_SYNC,也就是先等待复制,再提交事务,这样就不会丢数据。
设计理念:复制状态机

 任何一个存储系统,无论它存储的是什么数据,用什么样的数据结构,都可以抽象成一个状态机。存储系统中的数据称为状态(即MySQL中的数据),状态的全量备份称为快照(Snapshot),就像给数据拍个照片一样。按照顺序记录更新存储系统的每条操作命令,就是操作日志(Commit Log,即MySQL中的Binlog)。

基于binlog位点同步的主从复制原理

基于binlog位点同步的主从复制原理.png

1、主库会生成多个binlog日志文件。
2、从库的I/O线程请求指定文件和指定位置的binlog日志文件(位点)。
3、主库dump线程获取指定位点的binlog日志。
4、主库按照从库发送给来的位点信息读取binlog,然后推送binlog给从库。
5、从库将得到的 binlog 写到本地的relay log(中继日志)文件中。
6、从库的SQL线程读取和解析relay log文件。
7、从库的SQL线程重放relay log中的命令。
(从库请求指定的binlog位点,主库取指定位点的binlog日志,读取binlog,推送从库,从库将得到的binlog文件写入中继日志,然后从库SQL线程读取解析中继日志,重放中继日志中的命令。)
参考:MySQL :: MySQL 8.0 参考手册 :: 19.4.10.1 安装半同步复制
痛点:
 1.首次开启主从复制的步骤复杂
  第一次开启主从同步时,要求从库和主库是一致的。
  找到主库的binlog位点。
  设置从库的binlog位点。
  开启从库的复制线程
 2.恢复主从复制的步骤复杂
  找到从库复制线程停止时的位点。
  解决复制异常的事务。无法解决时就需要手动跳过指定类型的错误,比如通过设置slave_skip_errors=1032,1062。当然这个前提条件是跳过这类错误是无损的。(1062错误是插入数据时唯一键冲突;1032错误是删除数据时找不到行)
  不论是首次开启同步时需要找位点和设置位点,还是恢复主从复制时,设置位点和忽略错误,这些步骤都显得过于复杂,而且容易出错。所以MySQL 5.6版本引入了GTID,彻底解决了这个困难。

基于全局事务标识符(GTID)复制

 GTID是一个基于原始mysql服务器生成的一个已经被成功执行的全局事务ID,它由服务器ID以及事务ID组合而成。这个全局事务ID不仅仅在原始服务器器上唯一,在所有存在主从关系的mysql服务器上也是唯一的。

  • 一个GTID在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。
  • GTID用来代替传统复制方法,不再使用MASTER_LOG_FILE+MASTER_LOG_POS开启复制。而是使用MASTER_AUTO_POSTION=1的方式开始复制。
  • 在传统的replica端,binlog是不用开启的,但是在GTID中replica端的binlog是必须开启的,目的是记录执行过的GTID(强制)。
GTID工作原理

 主库计算主库GTID集合和从库GTID的集合的差集,主库推送差集binlog给从库。
 当从库设置完同步参数后,主库A的GTID集合记为集合x,从库B的GTID集合记为y。从库同步的逻辑如下:


GTID工作原理.png
  • 从库B指定主库A,基于主备协议建立连接。
  • 从库B把集合y发给主库A。
  • 主库A计算出集合 x 和集合y的差集,也就是集合x中存在,集合y中不存在的GTID集合。比如集合x是1到100,集合y是1到90,那么这个差集就是91到100。这里会判断集合x是不是包含有集合y的所有GTID,如果不是则说明主库A删除了从库B需要的binlog,主库A直接返回错误。
  • 主库A从自己的binlog文件里面,找到第一个不在集合y中的事务GTID,也就是找到了91。
  • 主库A从GTID = 91的事务开始,往后读binlog文件,按顺序取binlog,然后发给B。
  • 从库B的I/O线程读取 binlog 文件生成relay log,SQL线程解析relay log,然后执行SQL语句。
    (从库发GTID集合给主库,主库比较自己与从库的GTID集合,然后主库推送自己与从库间差异的binlog日志,从库写入中继日志relay log,然后利用SQL线程解析中继日志,重放SQL,例如插入更新删除,之后数据就完成同步。)
    GTID同步方案和位点同步的方案区别是:
  • 位点同步方案是通过人工在从库上指定哪个位点,主库就发哪个位点,不做日志的完整性判断。
  • 而GTID方案是通过主库来自动计算位点的,不需要人工去设置位点,对运维人员友好。

组复制

 由于传统异步复制的缺陷,可能会导致主从数据不一致的问题,在主节点异常宕机时从节点可能造成数据丢失。基于这个缺陷,Mysql5.7.17推出了一个高可用与高扩展的解决方案Mysql GroupReplication(简称MGR),将原有的gtid复制功能进行了增强,支持单主模式和多主模式。组复制在数据库层面上做到了只要集群中大多数主机可用,则服务可用,也就是说3台服务器的集群,允许其中1台宕机。

组复制.png

组通信协议(GCS)的工作原理:
 成员管理:
  每个节点定期向集群发送心跳信息,以表明其存活状态。
  如果某个节点长时间未发送心跳,GCS会将其标记为故障节点,并从集群中移除。
 消息广播:
  当一个节点需要向集群发送消息时,GCS会将该消息广播给所有其他节点。
  使用一致性算法确保所有节点以相同的顺序接收和处理消息。
 一致性保证:
  在事务提交前,GCS会协调所有节点对事务的合法性进行验证,并确保多数节点达成一致。
  只有在多数节点确认后,事务才会被提交。

组复制的核心机制包括:
 组成员管理:通过组通信协议(Group Communication System, GCS)管理集群中的节点,维护节点的状态;
 事务同步:当一个节点接收到写操作时,会将该事务广播到集群中的其他节点。其他节点验证事务并确认其合法性后,才会提交事务;
 一致性协议:使用基于Paxos的协议确保所有节点对事务的顺序和提交状态达成一致;
 故障处理:当某个节点发生故障时,组复制会将其从集群中移除,并重新选举新的主节点(在单主模式下)。

与传统复制相比,Group Replication有以下大幅改进:
 传统复制的主从复制方式有一个主和不等数量的从。主节点执行的事务会异步发送给从节点,在从节点重新执行。而Group Replication采用整组写入的方式,避免了单点争用。
 Group Replication在传输数据时使用了Paxos协议。Paxos协议保证了数据传输的一致性和原子性。基于Paxos协议,Group Replication构建了一个分布式的状态复制机制,这是实现多主复制的核心技术。
 Group Replication提供了多写方案,为多活方案带来了实现的可能。
无法处理如下问题:一个组成员变为不可用时,连接到它的客户端必须被重定向或故障转移到其他组成员。此时需要使用连接器、负载均衡器、路由器或某种形式的中间件,例如 MySQL Router 8.0。MGR本身不提供这些工具,此时便引入了InnoDB Cluster

单主模式(默认)

 组中的每个MySQL服务器实例都可以在独立的物理主机上运行,这是部署组复制的推荐方式。
 主节点拥有读写权限,从节点只拥有读的权限。
 在单主模式下(group_replication_single_primary_mode=ON),组中只有一个主服务器,该主服务器被设置为读写模式。组中的所有其他成员都被设置为只读模式(super_read_only=ON)(一个组&&一个主)。


单主模式.png
MySQL InnoDB Cluster

 InnoDB Cluster是MySQL官方实现高可用+读写分离的架构方案,其中包含以下组件:
 MySQL Group Replication,简称MGR,是MySQL的主从同步高可用方案,包括数据同步及角色选举
 Mysql Shell 是InnoDB Cluster的管理工具,用来创建和管理集群
 Mysql Router 是业务流量入口,支持对MGR的主从角色判断,可以配置不同的端口分别对外提供读写服务,实现读写分离
  自动路由规则:
   写请求:直接转发给主节点(Primary)。
   读请求:可负载均衡到只读副本(Read Replicas)。
  故障感知:
   实时监控集群状态,主节点切换后自动更新路由表(应用无感知)。
  Bootstrap机制:
   自动从集群拉取拓扑信息(主从关系)。
   生成路由配置文件(如mysqlrouter.conf)。
 MySQL Router与组复制和MySQL Shell高度整合,只有将其与组复制和MySQL Shell共同使用,才能够称为InnoDB Cluster。

InnoDB Cluster.png

 InnoDB Cluster将三个MySQL数据库实例构成一个高可用集群。其中一个实例是具有读/写能力的主要成员,其他两个实例是具有只读能力的次要成员。组复制将数据从主要成员复制到次要成员。MySQL Router将客户端应用程序连接到集群的主要成员。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容