百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

MySQL 主从复制不明白?本文带你轻松掌握

wptr33 2025-03-13 21:06 11 浏览

前言

近日,我的一位朋友正在寻觅实习机会,在前几日的面试中,被问及这样一个问题:“在您的项目中运用了 Canal 组件,您是否曾考虑过它存在数据丢失的情况?”我的这位朋友瞬间茫然,Canal 不就佯装充当一个数据库主从的从节点吗?对于此方面,确实未曾思考过,在网上搜寻了一些资料,亦未发现有文章提及此事。那么,今日咱们就从 MySQL 的主从复制来探讨一下这个问题。

下面是本文即将以下几个方面进行展开:

一、同步原理

于数据库系统之中,保障数据的一致性与高可用性实乃重中之重。MySQL 的主从同步机制借由将主节点(Master)上的变更复制至一个或多个从节点(Slave 或 Replica),达成了此目标。接下来,我们将深度探究这一过程的具体施行方式,并针对 binlog 日志的各异格式予以剖析。

1. 数据写入与日志记录

当客户端向主节点发出写入请求之际,主节点率先处理此请求,并将相应的变更应用于自身的数据存储之内。一旦数据得以成功写入,MySQL 会即刻生成一份二进制日志(binlog),详实记录下此次操作的具体信息。这一举措确保了所有针对数据库的修改皆能被精准地捕获,为后续的复制筑牢了根基。

2. Log Dump 线程与长连接通知机制

配置妥主从架构之后,主节点会为每一个连接的从节点开启一个专属的日志传输线程——Log Dump 线程。此线程负责持续监察 binlog 文件的变动,并借助一个具有持久性的 TCP 长连接实时地将最新的日志更新推送至对应的从节点。此种方式卓有成效地降低了延迟,保证从节点能够适时接收到最新的数据变更。

3. I/O 线程:拉取与缓存

在从节点这边,有一个或多个 I/O 线程专门用于接收来自主节点的通知并请求获取新的 binlog 内容。这些线程会在主节点的日志发生变动时被激活,然后批量拉取一定范围内的日志数据。为了缓解可能存在的生产消费速度不匹配问题,从节点会先将接收到的数据暂存于本地的中继日志(relay log)中,作为缓冲区使用。这样的设计类似于消息队列(MQ)中的削峰填谷策略,有助于维持系统的稳定运行。

4. SQL 线程:解析与执行

最后,在从节点上还有一个或多个 SQL 线程负责读取 relay log 中的内容,将其解析成可执行的操作,再依次应用到自己的数据库实例中。通过这种方式,从节点可以逐步追平主节点的状态,保持两者之间的一致性。

Binlog 日志格式的选择

MySQL 支持三种不同的 binlog 格式来记录数据变更:

  • Statement:此格式径直记录每一条会对数据库造成影响的 SQL 语句。虽则简单明了,但在某些情形下,它或许会致使主从之间的数据出现不一致的状况,诸如涉及非确定性函数(诸如 NOW()、UUID() 等)亦或依赖服务器状态的查询。
  • Row:相较之 Statement,Row 格式更为精细,其仅记录具体产生变化的数据行及其元数据。纵然如此能够规避多数由不确定因素引发的问题,然而倘若一次 DML 操作影响了众多的数据行,便会致使日志体积迅猛膨胀,增添存储与传输的负担。
  • Mixed:这乃是前两种格式的融合体,MySQL 会依据实际情形睿智地选取最为适宜的记录方式。对于那些无法稳妥地以 Statement 形式复制的操作,它会择取 Row 格式;而对于其余情况,则优先采用效率更高的 Statement 格式。故而,在构建主从架构之时,推荐运用 Mixed 格式,因其能够于性能和一致性之间获取优良的平衡。

二、主从架构

  1. 一主多从架构:适用于读大于写的场景,采用多个从库来分担数据库系统的读压力。
  1. 多主多从架构:适用于读写参半的场景,采用多个主库来承载数据库系统整体的读写压力。
  1. 多主一从架构:适用于写大于读的场景,采用多个主库分担写压力,单个从库承载读压力。
  1. 级联复制架构:适用于读大于写的场景,采用单个从节点来分担从库对主库造成的I/O压力。但是这种问题是延迟比其他主从更严重。

三、MySQL 主从复制方式详解

在分布式数据库环境中,确保数据的一致性和高可用性是至关重要的。MySQL 提供了多种主从复制模式来满足不同的应用场景需求。下面我们将详细介绍几种常见的 MySQL 主从复制方式,并分析它们各自的优缺点。

3.1 同步复制

同步复制是一种最为严格的复制模式,它要求主服务器在提交一个事务之前,必须等待所有从服务器确认接收到并应用了该事务之后,才会向客户端返回事务提交成功的消息。这意味着主服务器和从服务器之间存在紧密的交互,以确保每个事务都能被可靠地传播到整个集群中。

由上我们可得出,同步复制虽然满足了数据库多节点数据的强一致性,但是由于主节点的执行要等到所有从节点完成才返回,在当代系统中是万万不能接受的。

3.2 异步复制

异步复制是默认的主从同步模式,在这种模式下,主服务器提交事务后立即返回客户端,无需等待从服务器确认是否成功接收并应用了事务。从服务器会在后台独立地接收并应用事务日志。

异步复制虽然能解决同步复制的性能问题,但是没有完全的可靠,可能在一定程度还是会导致数据丢失的问题。

3.3 半同步复制

为了解决同步复制效率低下以及异步复制可能导致的数据丢失问题,MySQL 引入了半同步复制模式。在这种模式下,主服务器在提交事务后会等待至少一个从服务器确认接收到并应用了该事务,然后才向客户端返回提交成功的消息。此外,
rpl_semi_sync_master_timeout 参数(默认为10秒)用于控制主从之间没有响应时切换到异步复制的时间窗口。

  • 特点
    • 在一主多从架构中,只需一个从节点返回 ACK,即可认为事务已成功提交。
    • 如果指定时间内没有从节点返回 ACK,则自动降级为异步复制模式。

尽管如此,这种仅需一个节点确认的方式仍然存在一定的数据丢失风险。为了进一步提高可靠性,某些系统(如 Zookeeper)采用了更严格的一致性协议,例如 ZAB(Zookeeper Atomic Broadcast),要求超过一半的从节点确认后才向客户端返回成功。

3.4 增强式半同步复制/无损复制

增强式的半同步复制,也称为无损复制,改进了传统的半同步复制机制。其核心区别在于 ACK 的时机:

  • after-commit:传统半同步复制中,ACK 动作发生在事务提交之后。
  • after-sync:增强式半同步复制中,ACK 动作发生在事务同步过程中。

这种方式虽然增加了主库的开销——特别是当事务长时间未提交时可能导致锁资源占用——但它有效降低了数据丢失的风险,提高了数据的一致性和完整性。

3.5 延迟复制

延迟复制允许从服务器上的 SQL 线程在接收到主服务器的日志后,并不是立刻解析执行,而是根据设定的时间间隔(通常建议设置为3至6小时)延迟执行。这种方法主要用于防止误删操作对生产环境造成不可逆的影响,同时也便于进行线上 Bug 的实时观测与恢复。

  • 作用
    • 防误删:提供了一种“后悔药”机制,可以在一定时间内回滚错误的操作。
    • 线上 Bug 观测:对于难以复现的问题,可以通过检查延迟复制的从服务器状态来进行调试。

3.6 并行复制

随着 MySQL 版本的演进,并行复制技术得到了显著的发展,极大地提升了主从复制的效率和稳定性。以下是几种主要的并行复制形式:

3.6.1 GTID 复制

GTID(Global Transaction ID)复制自 MySQL 5.6 版本引入,旨在简化主从切换过程中的手动定位 binlog 位置的工作。通过为每个写事务分配唯一的全局标识符,GTID 复制使得从服务器能够自动跟踪和应用正确的事务,而无需依赖具体的 binlog 文件和位置信息。

  • 工作流程
  • 主服务器更新数据时,为每个写事务分配一个全局的 GTID,并将其记录到 Bin-log 中。
  • 从服务器的 I/O 线程拉取数据后,将读取到的内容写入 relay-log,并设置 gtid_next 值。
  • 从服务器的 SQL 线程执行前,会读取 gtid_next 值以确定接下来要解析的日志条目。
  • 执行过程中,SQL 线程会检查自身的 Bin-log 日志中是否已有对应的 GTID:
    • 如果有,说明该 GTID 对应的事务已经执行过,从服务器将忽略这条记录;
    • 如果没有,则解析并执行该 GTID 对应的 relay-log 记录,并将其记录到 Bin-log 中。

需要注意的是,由于 GTID 是基于事务实现的,因此它只适用于支持事务的存储引擎(如 InnoDB)。

3.6.2 组复制

组复制指的是将一组并行执行的事务作为一个整体放入同一个 GTID 中记录。这样做的好处是在后续同步数据时,可以从节点可以一次性读取并处理这一组事务,从而提高了复制效率。

3.6.3 库级别的并行复制

MySQL 5.6 版本首次引入了库级别的并行复制概念,但由于担心并行执行可能导致的无序性问题(例如,先改后删变为先删后改),该功能并未得到广泛应用。到了 MySQL 5.7 版本,真正的并行复制得以实现,即在同一时刻内提交且不存在锁冲突的多个事务可以由多个线程并行处理。这种设计不仅提升了复制速度,还保证了数据的一致性和正确性。

四、主从数据一致性解决方案

  1. 业务逻辑改动。在一些博客系统中,文章发布后加入一个审核状态,这里可能就是用于解决一个延迟导致的问题。
  2. 改动复制方式,采用全同步不会产生延迟,但性能会下降
  3. 调整数据库架构:采用分库分表代替主从集群
  4. 中间件Canal监听变更速度比从库拉取更快。
  5. 对于要求主从延迟低的数据,强制走主库

五、总结

  • 同步原理:深入解析了MySQL主从同步机制,包括数据写入、日志记录(binlog)、Log Dump线程、I/O线程和SQL线程的作用。确保读者理解整个复制流程以及不同日志格式(Statement、Row、Mixed)的选择对性能和一致性的影响。
  • 主从架构模式:探讨了几种常见的主从架构,如一主多从、多主多从、多主一从和级联复制架构,分别适用于不同的读写场景,并解释了它们各自的特点与适用性。
  • MySQL主从复制方式:详细介绍了多种复制模式——同步复制、异步复制、半同步复制、增强式半同步复制(无损复制)、延迟复制及并行复制(含GTID复制、组复制、库级别的并行复制)。每种方式都有其优缺点,适用于不同的需求场景。
  • 数据一致性解决方案:针对可能出现的数据不一致问题,提出了通过调整业务逻辑、改变复制方式、优化数据库架构或使用中间件(如Canal)等方法来提高主从之间的一致性。

至此,我们已经全面探讨了 MySQL 主从复制的原理、架构设计、不同复制方式的特点及适用场景,并深入分析了主从延迟问题及其多种解决方案。通过本文,我们不仅了解了如何选择合适的复制模式以满足不同的业务需求,还掌握了应对主从延迟挑战的有效策略。最后,我相信对于如何保证Canal的可靠性,你心里应该也有一个答案了吧。

希望本文能够为你提供有价值的参考和指导,帮助你在实际项目中更好地设计和优化数据库架构,确保系统的高性能、高可用性和数据一致性。如果你有任何疑问或需要进一步的帮助,请随时联系我们。感谢你的阅读!


作者:MAODO
链接:
https://juejin.cn/post/7449325849885474828


相关推荐

用Java实现RAG的3大核心模块与7个必知细节

一、真实场景驱动:某制造企业的知识管理之痛某汽车零部件企业有超过20万份技术文档(PDF/HTML/Word),工程师每天平均花费2小时查找资料。我们为其构建的Java版RAG系统,将查询耗时缩短至1...

在 C# .NET 中从 PDF 中提取表数据

概述:...

【分享】教你如何使用 Java 读取 Excel、docx、pdf 和 txt 文件

在Java开发中,我们经常需要读取不同类型的文件,包括Excel表格文件、"doc"和"docx"文档文件、PDF文件以及纯文本文件。其中最常用的是A...

Spring AI 模块架构与功能解析

SpringAI是Spring生态系统中的一个新兴模块,专注于简化人工智能和机器学习技术在Spring应用程序中的集成。本文将详细介绍SpringAI的核心组件、功能模块及其之间的关...

告别付费!一站式服务,PDF多功能工具!

大家好,我是Java陈序员。今天,给大家介绍一个PDF多功能在线操作工具,完全免费开源!...

本地PDF操作神器:永久告别盗版和破解,再也不用担心安全问题

前言PDF(便携式文档格式)目前已经成为了文档交换和存储的标准。然而,找到一个功能全面、安全可靠、且完全本地化的PDF处理工具并不容易。...

Python rembg 库去除图片背景

rembg是一个强大的Python库,用于自动去除图片背景。它基于深度学习模型(如U^2-Net),能够高效地将前景物体从背景中分离,生成透明背景的PNG图像。本教程将带你从安装到实际应用...

31个必备的python字符串方法,建议收藏

字符串是Python中基本的数据类型,几乎在每个Python程序中都会使用到它。...

python学习day1——输出格式化

print一般在控制台中我们用print进行输出,默认情况下,使用格式为:print(*objects,sep='',end='\n')第一个参数是我们要在控制台...

一张图认识Python(附基本语法总结)

一张图认识Python(附基本语法总结)一张图带你了解Python,更快入门,一张图认识Python(附基本语法总结)Python基础语法总结:1.Python标识符在Python里,标识符有字...

学习编程第188天 python编程 字典格式化

今天学习的是刘金玉老师零基础Python教程第84期,主要内容是python字典格式化。...

Python基础数据类型转换

Python中的基础数据类型转换可以分为隐式转换和显示转换。隐式转换是python解释器自动转换,显示转换是通过内置函数实现。无论哪种方式进行的转换,均为转换为对应类型的数据,而非改变原数据的类型。...

python之json基本操作

1.概述JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,它具有简洁、清晰的层次结构,易于阅读和编写,还可以有效的提升网络传输效率。Python标准库的...

Python之迭代器及其用法

前面章节中,已经对列表(list)、元组(tuple)、字典(dict)、集合(set)这些序列式容器做了详细的介绍。值得一提的是,这些序列式容器有一个共同的特性,它们都支持使用for循环遍历存储...

从初始化一个现代 python项目学习到的东西

uv我准备用uv初始化一个python项目环境我用的是苹果笔记本MacBookPro,具体的操作系统及硬件参数如下:...