【MySQL技术之旅】(4)这也许是你的知识盲区-[MySQL主从架构]之半同步机制

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 【MySQL技术之旅】(4)这也许是你的知识盲区-[MySQL主从架构]之半同步机制

MySQL的主从复制


  • 一般在大规模的项目上,都是使用MySQL的复制功能来创建MySQL的主从集群的。
  • 主要是可以通过为数据库服务器配置一个或多个备库的方式来进行数据同步。
  • 复制的功能不仅有利于构建高性能应用,同时也是高可用、可扩展性、灾难恢复、备份以及数据仓库等工作的基础。
  • 通过MySQL的主从复制来实现读写分离,相比单点数据库又读又写来说,提升了业务系统性能,优化了用户体验。
  • 另外通过主从复制实现了数据库的高可用,当主节点MySQL挂了的时候,可以用从库来顶上。





MySQL支持的复制方式


MySQL支持三种复制方式


  • 基于语句(Statement)的复制(也称为逻辑复制)主要是指,在主数据库上执行的SQL语句,在从数据库上会重复执行一遍。
  • 优点:MySQL默认采用的就是这种复制,效率比较高。
  • 缺点:如果SQL中使用uuid()、rand()等函数,那么复制到从库的数据就会有偏差。
  • 基于行(Row模式)的复制,指将更新处理后的数据复制到从数据库,而不是执行一边语句。从MySQL5.1的版本才被支持。
  • 混合复制(Mixed),默认采用语句复制,当发现语句不能进行精准复制数据时-(例如语句中含有uuid()、rand()等函数),采用基于行的复制。




主从复制原理


image.png


  • MySQL的复制原理概述上来讲大体可以分为这三步:
  1. 在主库上把数据更改,记录到二进制日志(Binary Log)中。
  2. 从库将主库上的日志复制到自己的中继日志(Relay Log)中。
  3. 备库读取中继日志中的事件,将其重放到备库数据之上。

下面来详细说一下复制的这三步:


  • 第一步:是在主库上记录二进制日志,
  • 首先主库要开启binlog日志记录功能,
  • 授权Slave从库可以访问的权限。


这里需要注意的一点就是binlog的日志里的顺序是按照事务提交的顺序来记录的而非每条语句的执行顺序。


  • 第二步:从库将binLog复制到其本地的RelayLog中。
  • 首先从库会启动一个工作线程,称为I/O线程,I/O线程跟主库建立一个普通的客户端连接,
  • 然后主库上启动一个特殊的二进制转储(binlog dump)线程,此转储线程会读取binlog中的事件。
  • 当追赶上主库后,会进行休眠,直到主库通知有新的更新语句时才继续被唤醒。


这样通过从库上的I/O线程和主库上的binlog dump线程,就将binlog数据传输到从库上的relaylog中了。


  • 第三步:从库中启动一个SQL线程,从relaylog中读取事件并在备库中执行,从而实现备库数据的更新。
  • 这种复制架构实现了获取事件和重放事件的解耦,运行I/O线程能够独立于SQL线程之外工作。
  • 这种架构也限制复制的过程,最重要的一点是在主库上并发运行的操作在备库中只能串行化执行,因为只有一个SQL线程来重放中继日志中的事件
  • 数据或存在延迟和不一致性,所以如果要保证数据的一致性,一定要在主库进行数据操作!




MySQL主从复制模式


MySQL的主从复制其实是支持,异步复制、半同步复制、GTID复制等多种复制模式的。


异步模式


MySQL的默认复制模式就是异步模式,主要是指MySQL的主服务器上的I/O线程,将数据写到binlong中就直接返回给客户端数据更新成功,不考虑数据是否传输到从服务器,以及是否写入到relaylog中。在这种模式下,复制数据其实是有风险的,一旦数据只写到了主库的binlog中还没来得急同步到从库时,就会造成数据的丢失。


  • 这种模式确也是效率最高的,因为变更数据的功能都只是在主库中完成就可以了,从库复制数据不会影响到主库的写数据操作。

image.png



这种异步复制模式虽然效率高,但是数据丢失的风险很大,所以就有介绍的半同步复制模式。




半同步模式


MySQL从5.5版本开始通过以插件的形式开始支持半同步的主从复制模式,什么是半同步主从复制模式呢?


  • 异步复制模式:主库在执行完客户端提交的事务后,只要将执行逻辑写入到binlog后,就立即返回给客户端,并不关心从库是否执行成功,这样就会有一个隐患,就是在主库执行的binlog还没同步到从库时,主库挂了,这个时候从库就就会被强行提升为主库,这个时候就有可能造成数据丢失。


  • 同步复制模式:当主库执行完客户端提交的事务后,需要等到所有从库也都执行完这一事务后,才返回给客户端执行成功。因为要等到所有从库都执行完,执行过程中会被阻塞,等待返回结果,所以性能上会有很严重的影响。


  • 半同步复制模式:半同步复制模式,可以说是介于异步和同步之间的一种复制模式,主库在执行完客户端提交的事务后,要等待至少一个从库接收到binlog并将数据写入到relay log中才返回给客户端成功结果。半同步复制模式,比异步模式提高了数据的可用性,但是也产生了一定的性能延迟,最少要一个TCP/IP连接的往返时间。


  • 半同步复制模式,可以很明确的知道,在一个事务提交成功之后,此事务至少会存在于两个地方一个是主库一个是从库中的某一个。
  • 在master的dump线程去通知从库时,增加了一个ACK机制,也就是会确认从库是否收到事务的标志码,master的dump线程不但要发送binlog到从库,还有负责接收slave的ACK。当出现异常时,Slave没有ACK事务相应,为了保证性能会那么将自动降级为异步复制,直到异常修复后再自动变为半同步复制。



MySQL半同步复制的流程如下

image.png



半同步复制的隐患


半同步复制模式也存在一定的数据风险,当事务在主库提交完后等待从库ACK的过程中,如果Master宕机了,这个时候就会有两种情况的问题。


  • 事务还没发送到Slave上:若事务还没发送Slave上,客户端在收到失败结果后,会重新提交事务,因为重新提交的事务是在新的Master上执行的,所以会执行成功,后面若是之前的Master恢复后,会以Slave的身份加入到集群中,这个时候,之前的事务就会被执行两次,
  • 第一次是之前此台机器作为Master的时候执行的,
  • 第二次是做为Slave后从主库中同步过来的。


  • 事务已经同步到Slave上:因为事务已经同步到Slave了,所以当客户端收到失败结果后,再次提交事务,你那么此事务就会再当前Slave机器上执行两次。


  • 为了解决上面的隐患,MySQL从5.7版本开始,增加了一种新的半同步方式,新的半同步方式的执行过程是将“Storage Commit”这一步移动到了“Write Slave dump”后面。


  • 这样保证了只有Slave的事务ACK后,才提交主库事务。MySQL 5.7.2版本新增了一个参数来进行配置:rpl_semi_sync_master_wait_point,此参数有两个值可配置:


  • AFTER_SYNC:参数值为AFTER_SYNC时,代表采用的是新的半同步复制方式。


  • AFTER_COMMIT:代表采用的是之前的旧方式的半同步复制模式。


image.png



MySQL从5.7.2版本开始,默认的半同步复制方式就是AFTER_SYNC方式了,但是方案不是万能的,因为AFTER_SYNC方式是在事务同步到Slave后才提交主库的事务的,若是当主库等待Slave同步成功的过程中Master挂了,这个Master事务提交就失败了,客户端也收到了事务执行失败的结果了,但是Slave上已经将binLog的内容写到Relay Log里了,这个时候,Slave数据就会多了,但是多了数据一般问题不算严重,多了总比少了好。


半同步复制模式的参数:


mysql> show variables like '%Rpl%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
| rpl_stop_slave_timeout                    | 31536000   |
+-------------------------------------------+------------+
复制代码


  • 半同步复制模式开关: rpl_semi_sync_master_enabled
  • rpl_semi_sync_master_timeout:半同步复制,超时时间,单位毫秒,当超过此时间后,自动切换为异步复制模式
MySQL 5.7.3引入的,该变量设置主需要等待多少个slave应答,才能返回给客户端,默认为1。
  • rpl_semi_sync_master_wait_for_slave_count:此值代表当前集群中的slave数量是否还能够满足当前配置的半同步复制模式,默认为ON,当不满足半同步复制模式后,全部Slave切换到异步复制,此值也会变为OFF
  • rpl_semi_sync_master_wait_no_slave: 代表半同步复制提交事务的方式,5.7.2之后,默认为AFTER_SYNC
  • rpl_semi_sync_master_wait_point




GTID模式


MySQL从5.6版本开始推出了GTID复制模式,GTID即全局事务ID (global transaction identifier)的简称,GTID是由UUID+TransactionId组成的,UUID是单个MySQL实例的唯一标识,在第一次启动MySQL实例时会自动生成一个server_uuid, 并且默认写入到数据目录下的

auto.cnf(mysql/data/auto.cnf)文件里。TransactionId是该MySQL上执行事务的数量,随着事务数量增加而递增。这样保证了GTID在一组复制中,全局唯一。


这样通过GTID可以清晰的看到,当前事务是从哪个实例上提交的,提交的第多少个事务。


来看一个GTID的具体形式:


mysql> show master status;
+-----------+----------+--------------+------------------+-------------------------------------------+
| File      | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+-----------+----------+--------------+------------------+-------------------------------------------+
| on.000003 |      187 |              |                  | 76147e28-8086-4f8c-9f98-1cf33d92978d:1-322|
+-----------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)
复制代码

GTID:76147e28-8086-4f8c-9f98-1cf33d92978d:1-322 UUID:76147e28-8086-4f8c-9f98-1cf33d92978d TransactionId:1-322




GTID的工作原理


由于GTID在一组主从复制集群中的唯一性,从而保证了每个GTID的事务只在一个MySQL上执行一次。那么是怎么实现这种机制的呢?GTID的原理又是什么样的呢?


  • 当从服务器连接主服务器时,把自己执行过的GTID(Executed_Gtid_Set: 即已经执行的事务编码)以及获取到GTID(Retrieved_Gtid_Set: 即从库已经接收到主库的事务编号)都传给主服务器。


  • 主服务器会从服务器缺少的GTID以及对应的transactionID都发送给从服务器,让从服务器补全数据。当主服务器宕机时,会找出同步数据最成功的那台conf服务器,直接将它提升为主服务器。
  • 若是强制要求某一台不是同步最成功的一台从服务器为主,会先通过change命令到最成功的那台服务器,将GTID进行补全,然后再把强制要求的那台机器提升为主。




主要数据同步机制可以分为这几步:


  • master更新数据时,在事务前生产GTID,一同记录到binlog中。
  • slave端的i/o线程,将变更的binlog写入到relay log中。
  • sql线程从relay log中获取GTID,然后对比Slave端的binlog是否有记录。
  • 如果有记录,说明该GTID的事务已经执行,slave会忽略该GTID。
  • 如果没有记录,Slave会从relay log中执行该GTID事务,并记录到binlog。
  • 在解析过程中,判断是否有主键,如果没有主键就使用二级索引,再没有二级索引就扫描全表。



GTID的优劣势


通过上面的分析我们可以得出GTID的优势是:


  • 每一个事务对应一个执行ID,一个GTID在一个服务器上只会执行一次;
  • GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置;
  • 减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机;



GTID的缺点:


  • 首先不支持非事务的存储引擎;


  • 不支持create table ... select 语句复制(主库直接报错);(原理: 会生成两个sql, 一个是DDL创建表SQL, 一个是insert into 插入数据的sql; 由于DDL会导致自动提交, 所以这个sql至少需要两个GTID, 但是GTID模式下, 只能给这个sql生成一个GTID)
  • 不允许一个SQL同时更新一个事务引擎表和非事务引擎表;
  • 在一个MySQL复制群组中,要求全部开启GTID或关闭GTID。
  • 开启GTID需要重启 (mysql5.7除外);
  • 开启GTID后,就不再使用原来的传统复制方式(不像半同步复制,半同步复制失败后,可以降级到异步复制);
  • 对于create temporary table 和 drop temporary table语句不支持;
  • 不支持sql_slave_skip_counter;



开启GTID的必备条件:


MySQL 5.6 版本,在my.cnf文件中添加:

gtid_mode=on (必选)                    #开启gtid功能
log_bin=log-bin=mysql-bin (必选)       #开启binlog二进制日志功能
log-slave-updates=1 (必选)             #也可以将1写为on
enforce-gtid-consistency=1 (必选)      #也可以将1写为on
MySQL 5.7或更高版本,在my.cnf文件中添加:
gtid_mode=on    (必选)
enforce-gtid-consistency=1  (必选)
log_bin=mysql-bin           (可选)    #高可用切换,最好开启该功能
log-slave-updates=1     (可选)       #高可用切换,最好打开该功能

















相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
379
分享
相关文章
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
Tiktokenizer 是一款现代分词工具,旨在高效、智能地将文本转换为机器可处理的离散单元(token)。它不仅超越了传统的空格分割和正则表达式匹配方法,还结合了上下文感知能力,适应复杂语言结构。Tiktokenizer 的核心特性包括自适应 token 分割、高效编码能力和出色的可扩展性,使其适用于从聊天机器人到大规模文本分析等多种应用场景。通过模块化设计,Tiktokenizer 确保了代码的可重用性和维护性,并在分词精度、处理效率和灵活性方面表现出色。此外,它支持多语言处理、表情符号识别和领域特定文本处理,能够应对各种复杂的文本输入需求。
58 6
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
DeepSeek背后的技术基石:DeepSeekMoE基于专家混合系统的大规模语言模型架构
DeepSeekMoE是一种创新的大规模语言模型架构,融合了专家混合系统(MoE)、多头潜在注意力机制(MLA)和RMSNorm归一化。通过专家共享、动态路由和潜在变量缓存技术,DeepSeekMoE在保持性能的同时,将计算开销降低了40%,显著提升了训练和推理效率。该模型在语言建模、机器翻译和长文本处理等任务中表现出色,具备广泛的应用前景,特别是在计算资源受限的场景下。
586 29
DeepSeek背后的技术基石:DeepSeekMoE基于专家混合系统的大规模语言模型架构
YOLOv11改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
YOLOv11改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
165 10
YOLOv11改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
RT-DETR改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
RT-DETR改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
47 4
RT-DETR改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型
MySQL的架构与SQL语句执行过程
MySQL架构分为Server层和存储引擎层,具有高度灵活性和可扩展性。Server层包括连接器、查询缓存(MySQL 8.0已移除)、分析器、优化器和执行器,负责处理SQL语句;存储引擎层负责数据的存储和读取,常见引擎有InnoDB、MyISAM和Memory。SQL执行过程涉及连接、解析、优化、执行和结果返回等步骤,本文详细讲解了一条SQL语句的完整执行过程。
49 3
MySQL原理简介—2.InnoDB架构原理和执行流程
本文介绍了MySQL中更新语句的执行流程及其背后的机制,主要包括: 1. **更新语句的执行流程**:从SQL解析到执行器调用InnoDB存储引擎接口。 2. **Buffer Pool缓冲池**:缓存磁盘数据,减少磁盘I/O。 3. **Undo日志**:记录更新前的数据,支持事务回滚。 4. **Redo日志**:确保事务持久性,防止宕机导致的数据丢失。 5. **Binlog日志**:记录逻辑操作,用于数据恢复和主从复制。 6. **事务提交机制**:包括redo日志和binlog日志的刷盘策略,确保数据一致性。 7. **后台IO线程**:将内存中的脏数据异步刷入磁盘。
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
99 3
云原生架构下的微服务治理与挑战####
随着云计算技术的飞速发展,云原生架构以其高效、灵活、可扩展的特性成为现代企业IT架构的首选。本文聚焦于云原生环境下的微服务治理问题,探讨其在促进业务敏捷性的同时所面临的挑战及应对策略。通过分析微服务拆分、服务间通信、故障隔离与恢复等关键环节,本文旨在为读者提供一个关于如何在云原生环境中有效实施微服务治理的全面视角,助力企业在数字化转型的道路上稳健前行。 ####
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
376 69
从单体到微服务:如何借助 Spring Cloud 实现架构转型

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等