MySQL高可用架构探秘:主从复制剖析、切换策略、延迟优化与架构选型

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL高可用架构探秘:主从复制剖析、切换策略、延迟优化与架构选型

MySQL高可用的基石

在分布式系统中,单机节点在发生故障时无法提供服务,这可能导致长期的服务不可用,从而影响其他节点的运作,导致的后果非常严重

为了满足服务的高可用,往往是通过节点冗余(新增相同功能的从节点),当发生故障时进行主从切换,让从节点成为新的主节点来继续提供服务

比如:MySQL的主从、Redis的主从、MQ broker的主从...思想大体类似的

作为高可用的基石——主从架构功不可没,本篇文章就来聊聊MySQL的主从的一些细节

image.png

binlog

binlog作为逻辑上恢复数据的日志,是主从数据同步、数据恢复的基础

binlog分为三种格式:statement、row、mixed

statement :记录写操作的SQL,语句轻量、传输快,使用该格式可能会导致数据不一致(因为从机与主机所处的环境不同,比如从机时间与主机不同时,使用now()函数)

row : 记录数据的修改,数据量大、传输慢,误操作时可以恢复数据(反向操作),主从同步时数据一致

mixed :结合statement、row的优点,自动混合选择格式

大多数情况下都是选择格式为row,因为数据一致并且可以恢复数据

主从复制

往期文章中说过当收到写操作需要修改数据时,为了满足数据的一致性,会写undo log(原子性)、redo log(持久性)、binlog等日志

当主节点接收到写操作更改数据时,也需要对从节点进行数据的修改以此来达到数据一致

在主从复制数据依靠的就是binlog,大致流程分为三个阶段:

  1. 主节点dump线程监听binlog变动通知从节点
  2. 从节点使用IO线程接收binlog并将其写入本地 relay log(中继日志)
  3. 从节点使用SQL线程根据relay log恢复数据

image.png

在单机中写完日志即可提交事务响应,而在主从中根据响应阶段的不同,主从复制的方式分为多种:

同步复制:所有从节点都响应(恢复完数据)主节点才响应,性能差、数据强一致

异步复制:主节点通知完从节点就立马响应,性能最好,存在延迟有数据一致性问题

半同步复制:只要有一个从节点响应主节点就响应,一主一从下与同步复制一致,网络超时退化为异步复制

增强半同步复制:在半同步复制的基础上,主节点收到响应后才提交事务,数据一致性会比半同步好,但性能稍差

延迟复制:从节点延迟一段时间恢复数据,这样即使发生误操作也可以进行回滚数据

主从切换

当主机发生故障时需要将从机切换为主机

不同策略

一般中间件的主从切换都只能在CAP理论中满足其二,即在分区容错(P)下只能满足可靠(C)或可用(A)

binlog上会记录主节点写操作的时间,从节点会维护一个 seconds_behind_master 来记录主从延迟的时间

在可靠策略下,需要等到旧的从节点完成所有的数据恢复(即seconds_behind_master为0)才成为主节点,提供写服务

image.png

在此期间只提供读服务、无法提供写服务,因此可靠策略会损失一定的可用性,取决于主从延迟的时间

在可用策略下会立即将从节点设置为新的主节点提供读写服务,某些场景下可能导致数据不一致

假设id自增,记录格式为(id,name),新增数据a,b,c

  1. 主节点已经新增(1,a),(2,b),(3,c)时宕机
  2. 从节点可能只重做数据(1,a),(2,b) 而(3,c)还在中继日志中
  3. 此时旧的从节点成为新的主节点又继续提供写服务,需要新增d,新增完d后才将中继日志的数据进行恢复

image.png

如果使用的binlog格式为statement或mixed,则会新增为(3,d)和(4,c)

image.png

如果格式为row,则会主键冲突报错,新增(3,d)后中继日志为(3,c)

image.png

在可用策略下可能导致数据不一致,使用row会提前暴露数据不一致的问题

基于GTID的主从切换

GTID 全局事务ID

格式为 server_uuid:gno

server_uuid 为节点标识

gno 为事务标识(事务提交时获得,全局自增)

在进行主从切换时,每个从节点同步数据的日志偏移量都不同,一般会找最新偏移量的从节点为新的主节点(这个偏移量是需要运维去定位的)

在GTID 全局事务ID出来后,binlog中每个事务有对应的GTID则可以通过GTID自动定位偏移量,不用手动定位

主从延迟

来源

默认情况下主从复制会使用异步复制,而在主从架构下一般会使用读写分离,主机服务写操作,从机服务读操作

由于使用异步复制,主从之间的数据一致性会存在一定的延迟,物理上主从会放在同一机房中,网络通信忽略不计,成本最大的就是从机SQL线程解析日志恢复数据的过程

如果恢复数据是一些大事务时会导致很长的延迟,比如在主机上执行批量操作耗时5s,在从机上执行时也会耗时那么久(资源大概一致)

可能写完操作就会进行读操作,如果此时从库还未重做数据就会导致写完查不到的数据不一致情况

先来看看哪些情况可能会导致主从延迟太长:

  1. 业务高峰期频繁读写(高TPS),从机不仅要同步数据,还要处理读操作
  2. 处理大事务,大事务导致延迟时间太久
  3. 从机硬件配置低,导致跟不上主机IO速度
  4. 主从机器可能参数不同(缓冲池、IO参数...)
  5. 从机本身就是延迟复制

...

当主从延迟过长时可以考虑使用方案缩短延迟:

  1. 调整redo log\bin log刷盘策略,增强IO
  2. canal监听(通知改为监听)
  3. 从机并行复制

从机并行复制借助于redo log、bin log两阶段提交时,redo log prepare阶段不会有锁冲突,可以并行执行

并行复制就是基于两阶段提交中的组提交,可以调整以下两个参数拉长组提交的时间,减慢主机写,加快从机重做数据

binlog_group_commit_sync_delay 延迟多少微秒后才调用 fsync

binlog_group_commit_sync_no_delay_count 累积多少次以后才调用 fsync

数据不一致解决方案

为了避免长时间的主从延迟,从机应该和主机有相同的参数、配置,并且要避免大事务

在业务高峰期还是可能存在主从延迟导致数据不一致,需要使用一些方案进行避免:

  1. 沟通业务:等待一段时间,比如用户修改完资料后进行审核状态
  2. 强一致性的读也走主库:这样就不存在主从延迟,使用方便,大量强一致性读操作就会导致主机压力大
  3. 等待从机没延迟(三种判断方式):
  • 比较 seconds_behind_master 是否为0,为0说明没延迟
  • 比较主从上的位点 Master_Log_File 和 Read_Master_Log_Pos(主库的最新位点)Relay_Master_Log_File 和 Exec_Master_Log_Pos(备库执行的最新位点)判断是否相同,相同则没延迟
  • 比较从机上GTID集合 Retrieved_Gtid_Set 和 Executed_Gtid_Set (备库收到的所有日志的 GTID 集合 和 备库所有已经执行完成的 GTID 集合)是否相同,相同则没延迟
  1. 这个方案粒度大(实际上只需要判断事务是否重做,这里是一直判断是否有延迟),如果高峰期一直有延迟就会一直等待判断,不使用
  2. 修改主从复制方式为同步复制:数据强一致性,性能差
  3. 修改主从复制方式为半同步复制:一主一从下与同步复制相同,一主多从下查询不确定,需要判断该事务是否已重做

方案5需要做到细粒度的判断事务是否在从机上已经重做,有两种方式且实现较为复杂

判断偏移量

select master_pos_wait(file, pos,[timeout]) 用于判断当前偏移量是否已经超过该位置

file 为 binlog 文件,pos 为 偏移量,timeout为等待的时间

使用半同步复制时,一个从节点已经响应,其他从节点应该也是快要响应的状态,因此可以等待一段时间 50ms,100ms...

如果超时则可以在业务中再去查主机,要注意如果都超时就相当于又全打在主机上

通过该SQL能够以主库日志中偏移量的方式判断是否已执行该事务(已执行返回0):

  1. 写操作完成时顺便获取binlog文件和偏移量的信息
  2. 携带这两个参数加上超时时间使用该SQL判断是否已执行
  3. 如果返回0(已执行)则查从机,否则查主机(注意限流)

判断GTID

判断GTID的思路与上面相似

select wait_for_executed_gtid_set(gtid_set, [timeout])

SQL的作用是判断是否已经执行GTID集合 返回0,超时返回1

流程类似:

  1. 写操作时获取GTID集合
  2. 根据GTID集合判断从机是否已执行事务
  3. 已执行查询,否则查主库或限流

主从架构

由于binlog的数据复制,主从架构可以非常丰富,想怎么搭就怎么搭

一主一从:主负责写,从负责读,读写压力平分

一主多从:主负责写,从负责读,适合读多于写

双主热备:两个节点互为主从,读写压力平分,但存在循环同步的问题

当AB节点互为主从时,A收到写请求,要把bin log给B重做,B重做完(相当于写请求)又会把bin log给A重做,这样就会导致循环同步数据

在同步数据时携带节点的id(server id)解决循环同步问题

A收到写请求,binlog给B并携带自己的id,B重做完又把binlog给A,A发现binlog上server id是自己则不进行重做

总结

本篇文章以MySQL高可用为起点,聊到MySQL中的主从复制、切换、延迟、架构等

binlog的statement格式记录SQL,数据量小、传输快,但可能导致数据不一致

binlog的row格式记录修改数据,数据量大,传输慢,可以修复误操作数据

binlog的mixed混用statement、row的优点,在可用策略的主从切换还是会导致数据不一致

主从复制时主机dump线程监听binlog变更通知从机拉取,从机io线程将日志写入realy log中继日志,再由sql线程解析日志重做数据

同步复制需要所有从机响应,拥有强一致性,但性能最差

默认的异步复制性能最好,但可能延迟时会有数据一致性

半同步复制只需要一个从机响应,多从下性能好于同步复制,网络超时会使用异步复制

增强的半同步复制会在从机响应时才提交事务,相比于半同步复制一致性略好

延迟复制可以让从机延迟一段时间重做数据,误操作数据可以恢复

主从切换时只能满足CAP中其二,满足可靠会导致一段时间不可写,满足可用可能会出现数据不一致

把从机参数、配置调整为主机相同,避免使用大事务可以避免主从延迟太长

当主从延迟太长可以通过调整从机IO参数增强IO能力

发生主从延迟的数据一致性问题时:

  1. 沟通业务,能否使用审核等中间状态,等延迟过了再查看
  2. 强制走主机,注意压力可能太大
  3. 使用同步复制,性能差
  4. 使用半同步复制,一主多从下需要判断事务是否执行(偏移量/GTID),实现困难

常用的主从架构有:一主一从、一主多从、双主热备(通过server id解决循环同步问题)...

最后(不要白嫖,一键三连求求拉~)

本篇文章被收入专栏 MySQL进阶之路,感兴趣的同学可以持续关注喔

本篇文章笔记以及案例被收入 gitee-StudyJavagithub-StudyJava 感兴趣的同学可以stat下持续关注喔~

有什么问题可以在评论区交流,如果觉得菜菜写的不错,可以点赞、关注、收藏支持一下~

关注菜菜,分享更多干货,公众号:菜菜的后端私房菜

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6天前
|
缓存 关系型数据库 MySQL
MySQL执行计划选择策略:揭秘查询优化的艺术
【10月更文挑战第15天】 在数据库性能优化中,选择最优的执行计划是提升查询效率的关键。MySQL作为一个强大的关系型数据库管理系统,提供了复杂的查询优化器来生成执行计划。本文将深入探讨如何选择合适的执行计划,以及为什么某些计划更优。
20 2
|
1天前
|
缓存 关系型数据库 MySQL
如何优化 MySQL 数据库的性能?
【10月更文挑战第28天】
7 1
|
8天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:优化百万数据查询的实战经验
【10月更文挑战第13天】 在处理大规模数据集时,传统的关系型数据库如MySQL可能会遇到性能瓶颈。为了提升数据处理的效率,我们可以结合使用MySQL和Redis,利用两者的优势来优化数据查询。本文将分享一次实战经验,探讨如何通过MySQL与Redis的协同工作来优化百万级数据统计。
26 5
|
2天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
10 0
|
3天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
16 0
|
24天前
|
缓存 监控 API
探索微服务架构中的API网关模式
【10月更文挑战第5天】随着微服务架构的兴起,企业纷纷采用这一模式构建复杂应用。在这种架构下,应用被拆分成若干小型、独立的服务,每个服务围绕特定业务功能构建并通过HTTP协议协作。随着服务数量增加,统一管理这些服务间的交互变得至关重要。API网关作为微服务架构的关键组件,承担起路由请求、聚合数据、处理认证与授权等功能。本文通过一个在线零售平台的具体案例,探讨API网关的优势及其实现细节,展示其在简化客户端集成、提升安全性和性能方面的关键作用。
69 2
|
28天前
|
存储 缓存 监控
探索微服务架构中的API网关模式
【10月更文挑战第1天】探索微服务架构中的API网关模式
80 2
|
1天前
|
运维 NoSQL Java
后端架构演进:微服务架构的优缺点与实战案例分析
【10月更文挑战第28天】本文探讨了微服务架构与单体架构的优缺点,并通过实战案例分析了微服务架构在实际应用中的表现。微服务架构具有高内聚、低耦合、独立部署等优势,但也面临分布式系统的复杂性和较高的运维成本。通过某电商平台的实际案例,展示了微服务架构在提升系统性能和团队协作效率方面的显著效果,同时也指出了其带来的挑战。
15 4
|
8天前
|
监控 Cloud Native Java
云原生架构下微服务治理策略与实践####
【10月更文挑战第20天】 本文深入探讨了云原生环境下微服务架构的治理策略,通过分析当前技术趋势与挑战,提出了一系列高效、可扩展的微服务治理最佳实践方案。不同于传统摘要概述内容要点,本部分直接聚焦于治理核心——如何在动态多变的分布式系统中实现服务的自动发现、配置管理、流量控制及故障恢复,旨在为开发者提供一套系统性的方法论,助力企业在云端构建更加健壮、灵活的应用程序。 ####
52 10
|
1天前
|
弹性计算 Kubernetes Cloud Native
云原生架构下的微服务设计原则与实践####
本文深入探讨了在云原生环境中,微服务架构的设计原则、关键技术及实践案例。通过剖析传统单体架构面临的挑战,引出微服务作为解决方案的优势,并详细阐述了微服务设计的几大核心原则:单一职责、独立部署、弹性伸缩和服务自治。文章还介绍了容器化技术、Kubernetes等云原生工具如何助力微服务的高效实施,并通过一个实际项目案例,展示了从服务拆分到持续集成/持续部署(CI/CD)流程的完整实现路径,为读者提供了宝贵的实践经验和启发。 ####

热门文章

最新文章

推荐镜像

更多