MySQL45讲 第二十五讲 高可用性深度剖析:从主备原理到策略选择

文章目录

  • MySQL45讲 第二十五讲 高可用性深度剖析:从主备原理到策略选择
    • 一、MySQL 主备基础原理
      • (一)主备关系与数据同步
      • (二)主备切换流程
    • 二、主备延迟分析
      • (一)主备延迟的定义与计算
      • (二)主备延迟的来源
    • 三、主备切换策略
      • (一)可靠性优先策略
      • (二)可用性优先策略
      • (三)策略选择的权衡
    • 四、异常切换情况
      • (一)异常切换流程
      • (二)对可用性的影响
    • 五、总结与思考

MySQL45讲 第二十五讲 高可用性深度剖析:从主备原理到策略选择

在当今数字化时代,数据库的高可用性对于企业的业务连续性至关重要。MySQL 作为广泛使用的关系型数据库管理系统,其高可用性机制一直备受关注。今天,我们将深入探讨 MySQL 是如何保证高可用性的,这涉及到主备关系中的数据同步、主备延迟的产生原因及应对策略,以及主备切换时可靠性优先和可用性优先策略的权衡。


一、MySQL 主备基础原理

(一)主备关系与数据同步

在 MySQL 的主备关系中,每个备库接收主库的 binlog 并执行,以此来保持数据一致。正常情况下,主库执行更新生成的 binlog 能顺利传到备库并被正确执行,备库就能达到与主库一致的状态,这就是最终一致性。例如,在一个简单的一主一备架构中,主库上的数据更新操作会被记录到 binlog 中,备库通过读取和执行这些 binlog,实现数据的同步更新。

(二)主备切换流程

我们来看双 M 结构的主备切换流程(如下图所示)。

在这里插入图片描述

在状态 1 时,客户端的读写直接访问主库 A,备库 B 作为主库 A 的备库,通过同步 A 的更新来保持数据一致。此时,通常建议将备库 B 设置为只读(readonly)模式,原因如下:

  1. 防止运营类查询语句在备库上的误操作。例如,运营人员可能在备库上执行一些临时查询,如果备库可写,可能会不小心修改数据,导致主备数据不一致。
  2. 避免切换逻辑出现 bug,如双写导致主备不一致。如果备库可写,在主备切换过程中可能会出现同时写入主库和备库的情况,破坏数据的一致性。
  3. 可依据 readonly 状态判断节点角色。在运维过程中,通过查看节点的 readonly 状态,可以快速确定其是主库还是备库,便于管理和维护。
  4. 虽然设置为 readonly,但用于同步更新的线程拥有超级权限,仍可进行数据同步。这样既能保证备库的只读性,又能确保数据的同步正常进行。

当需要切换时,客户端读写访问切换到备库 B,此时备库 B 成为主库,原主库 A 成为备库。


二、主备延迟分析

(一)主备延迟的定义与计算

  1. 相关时间点
    • 主库 A 执行完成一个事务,写入 binlog 的时刻记为 T1。
    • 备库 B 接收完这个 binlog 的时刻记为 T2。
    • 备库 B 执行完成这个事务的时刻记为 T3。
    • 主备延迟就是同一个事务在备库执行完成的时间和主库执行完成的时间之间的差值,即 T3 - T1
  2. 计算方法
    • 可以在备库上执行 show slave status 命令,其返回结果中的 seconds_behind_master 用于表示当前备库延迟了多少秒。seconds_behind_master 的计算方法是:每个事务的 binlog 里面都有一个时间字段,用于记录主库上写入的时间备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到 seconds_behind_master。实际上,seconds_behind_master 计算的就是 T3 - T1,其时间精度是秒。
  3. 系统时间不一致的影响
    • 若主备库机器的系统时间设置不一致,不会导致主备延迟的值不准。因为备库连接到主库的时候,会通过执行 SELECT UNIX_TIMESTAMP () 函数来获得当前主库的系统时间。如果发现主库的系统时间与自己不一致,备库在执行 seconds_behind_master 计算的时候会自动扣掉这个差值。

(二)主备延迟的来源

  1. 备库性能较差
    • 在一些部署中,备库所在机器的性能比主库所在机器性能差。例如,有人认为备库没有请求,所以使用较差的机器,或者将多个主库放在少数性能较好的机器上,而把备库集中在一台性能较差的机器上。然而,更新请求对 IOPS 的压力在主库和备库上并无差别,这种部署可能导致备库在处理事务时资源不足,从而造成主备延迟。不过,现在这种不对称部署情况较少,更多的是采用主备库选用相同规格机器并做对称部署的方式。
  2. 备库压力大
    • 一种常见情况是,主库提供写能力,备库提供读能力,同时一些运营后台需要的分析语句也在备库上运行。由于主库直接影响业务,使用时会比较克制,而备库的压力容易被忽视。大量的查询操作可能耗费备库大量的 CPU 资源,影响同步速度,进而造成主备延迟。针对这种情况,可以采用一主多从的方式,让多个从库分担读的压力;或者通过 binlog 输出到外部系统(如 Hadoop),让外部系统提供统计类查询的能力。其中,一主多从的方式较为常用,因为从库还适合用于定期全量备份。
  3. 大事务
    • 大事务是导致主备延迟的另一个重要原因。主库上必须等事务执行完成才会写入 binlog 并传给备库,所以如果一个主库上的语句执行时间很长,如一次性删除大量数据或执行大表 DDL 操作,就会导致从库延迟。例如,一些归档类数据在删除时,如果一次性删除过多,可能会使备库延迟很长时间。对于计划内的大表 DDL 操作,建议使用 gh - ost 方案来减少对主备延迟的影响。
  4. 备库的并行复制能力
    • 备库的并行复制能力也会影响主备延迟,这将在下一篇文章中详细介绍。此外,还有其他一些情况可能导致主备延迟,如主库 DML 语句并发大、从库服务器配置差、主库和从库参数配置不一样、从库上在进行备份操作、表上无主键(主库利用索引更改数据,备库回放只能用全表扫描)、设置的是延迟备库、备库空间不足等。

三、主备切换策略

(一)可靠性优先策略

在这里插入图片描述

  1. 切换流程
    • 在双 M 结构下,从状态 1 到状态 2 切换时,可靠性优先策略的详细过程如下:
      • 判断备库 B 现在的 seconds_behind_master,如果小于某个值(如 5 秒)继续下一步,否则持续重试这一步。这一步的目的是确保备库与主库的延迟在可接受范围内,避免切换后出现数据不一致的情况。
      • 把主库 A 改成只读状态,即把 readonly 设置为 true。这可以防止在切换过程中主库有新的数据写入,保证数据的一致性。
      • 判断备库 B 的 seconds_behind_master 的值,直到这个值变成 0 为止。这一步需要等待备库完全同步主库的数据,确保切换后的数据准确性。
      • 把备库 B 改成可读写状态,也就是把 readonly 设置为 false。此时备库 B 成为新的主库,可以接受读写请求。
      • 把业务请求切到备库 B,完成主备切换。
  2. 不可用时间分析
    • 这个切换流程中存在不可用时间。在步骤 2 之后,主库 A 和备库 B 都处于 readonly 状态,系统处于不可写状态,直到步骤 5 完成后才能恢复。其中,步骤 3 可能需要耗费较长时间,这也是为什么需要在步骤 1 先做判断,确保 seconds_behind_master 的值足够小。如果一开始主备延迟就很长,如长达 30 分钟,而不先做判断直接切换,系统的不可用时间就会很长,这对业务来说可能是不可接受的。

(二)可用性优先策略

在这里插入图片描述

  1. 切换流程与数据不一致示例
    • 如果强行把步骤 4、5 调整到最开始执行,即不等主备数据同步,直接把连接切到备库 B 并让其可读写,系统几乎没有不可用时间,但可能出现数据不一致的情况。
    • 例如,假设有一个表 t 定义了自增主键 id,初始化数据后,主库和备库上都是 3 行数据。业务人员要执行两条插入语句,在插入一条 c = 4 的语句后发起主备切换(假设此时主备延迟达到 5 秒)。
    • 主库 A 执行完 insert 语句,插入了一行数据 (4,4) 后开始切换。由于主备延迟,备库 B 还没来得及应用 “插入 c = 4” 的中转日志,就开始接收客户端 “插入 c = 5” 的命令,此时备库 B 插入了一行数据 (4,5),并把 binlog 发给主库 A。接着备库 B 执行 “插入 c = 4” 的中转日志,插入了一行数据 (5,4),而直接在备库 B 执行的 “插入 c = 5” 语句传到主库 A 后,插入了一行新数据 (5,5)。最终,主库 A 和备库 B 上出现了两行不一致的数据。
  2. binlog 格式对数据一致性的影响
    • 当设置 binlog_format = row 时,数据不一致的问题更容易被发现。因为 row 格式在记录 binlog 时会记录新插入行的所有字段值,所以最后只会有一行不一致,且两边的主备同步应用线程会报错 duplicate key error 并停止。而使用 mixed 或 statement 格式的 binlog 时,数据很可能悄悄地就不一致了,如果过了很久才发现数据不一致问题,可能这时的数据不一致已经不可查,或者连带造成了更多的数据逻辑不一致。

(三)策略选择的权衡

  1. 可靠性优先的建议
    • 大多数情况下,建议使用可靠性优先策略。因为对数据服务来说,数据的可靠性一般要优于可用性。保证数据准确是数据库服务的底线,在此基础上,通过减少主备延迟来提升系统的可用性。
  2. 可用性优先的适用场景
    • 然而,也存在一些情况数据的可用性优先级更高。例如,有一个库用于记录操作日志,数据不一致可以通过 binlog 来修补,且短暂的不一致不会引发业务问题,同时业务系统依赖于这个日志写入逻辑,如果库不可写会导致线上业务操作无法执行。在这种情况下,可以选择先强行切换,事后再补数据的策略。但事后复盘时,应考虑改进措施,如让业务逻辑不依赖于这类日志的写入,将日志写入逻辑模块降级,写到本地文件或另一个临时库中,这样就可以再次使用可靠性优先策略。

四、异常切换情况

在这里插入图片描述

(一)异常切换流程

假设主库 A 和备库 B 间的主备延迟是 30 分钟,此时主库 A 掉电,HA 系统要切换 B 作为主库。按照可靠性优先策略,必须等到备库 B 的 seconds_behind_master = 0 之后才能切换。但此时由于主库 A 掉电,连接还未切到备库 B,系统处于完全不可用状态。如果直接切换到备库 B 且保持 B 只读也不行,因为中转日志还未应用完成,客户端查询可能会认为有 “数据丢失”,虽然数据最终会恢复,但查询到 “暂时丢失数据的状态” 对一些业务来说是不可接受的。

(二)对可用性的影响

从这个例子可以看出,在满足数据可靠性的前提下,MySQL 高可用系统的可用性依赖于主备延迟。延迟时间越小,在主库故障时服务恢复所需时间就越短,可用性就越高。


五、总结与思考

MySQL 通过主备机制实现高可用性,主备数据同步基于 binlog。主备延迟的产生有多种原因,包括备库性能、压力、大事务以及并行复制能力等。在主备切换时,可靠性优先策略能保证数据一致性但可能存在不可用时间,可用性优先策略可减少不可用时间但可能导致数据不一致。在实际应用中,应根据业务需求权衡选择合适的策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/61476.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一篇文章了解机器学习(下)

一、决策树 1、主要应用场景为分类的问题。采用“树”的理念,通过计算数据的信息熵确定树的根节点、channel,从而加快数据分类。 注:与常规二分类树的区别:决策树中通过依据树的广度与深度,不断确定根节点的root值&a…

深入解析QP算法及其Python实现

目录 深入解析QP算法及其Python实现第一部分:QP算法的基本原理与数学模型1.1 QP问题定义1.2 算法核心思想1.3 应用场景第二部分:QP算法的Python实现(面向对象设计)2.1 核心代码实现第三部分:案例1 - 投资组合优化问题(策略模式)3.1 问题描述3.2 代码实现3.3 设计模式分析…

VuePress v2 快速搭建属于自己的个人博客网站

目录 为什么用VuePress? 一、前期准备 Node.js 使用主题快速开发 二、VuePress安装 三、个性化定制 修改配置信息 删除不需要的信息 博客上传 四、部署 使用github快速部署 初始化仓库 本地配置 配置github的ssh密钥 部署 为什么用VuePress&#xff…

前端开发调试之 PC 端调试学习笔记

一、引言 在前端开发过程中,调试是至关重要的一个环节。它能帮助我们快速定位代码中的问题,无论是页面布局错乱、交互效果异常还是性能不佳等情况,通过有效的调试手段都可以找到根源并进行修复。而在 PC 端进行调试有着其特定的方法和技巧&am…

PostgreSQL常用时间函数与时间计算提取示例说明

文章目录 常用函数与常量to_timestamp(字符串转时间戳、数字转时间戳)date与to_date(字符串转日期、时间戳转日期)interval(时间计算)基本操作与格式混合运算 to_char(各种时间转字符串)extract(提取时间字段,年月日时分秒,周、季度,第几周、…

SlickGrid点击/双击事件

分析 SlickGrid提供了点击事件方法grid.onClick和grid.onDblClick用于捕获用户对表格列的点击,捕获到点击事件之后,修改表格数据,然后使用grid.updateRow方法将修改后的数据更新到表格中。 展示 代码 创建grid(HTML)…

iOS UI 自动化 手势右滑退出当前页面

1、TouchAction from appium.webdriver.common.touch_action import TouchAction# 获取屏幕的宽度和高度 screen_width driver.get_window_size()["width"] screen_height driver.get_window_size()["height"]# 定义滑动的起点和终点坐标 start_x 0 en…

【Unity ShaderGraph实现流体效果之Node入门(二)】

Unity ShaderGraph实现流体效果之Node入门(二) 前言Shader Graph NodeStep NodeMultiply NodeRotate About AxisAddfresnel effectIs Front Face 前言 在(一)中讨论了一部分在制作流体效果时使用的Node,本章继续将剩余…

Redis 6.2 源码导读

Redis 是一个高性能的开源内存键值数据库,广泛用于缓存、会话管理和实时分析。Redis 6.2 版本引入了一些新特性和改进。 以下是 Redis 6.2 源码的一些关键部分和导读: 1. 源码结构 Redis 的源码主要分布在以下几个目录中: src/&#xff1…

集合卡尔曼滤波(Ensemble Kalman Filter),用于二维滤波(模拟平面上的目标跟踪),MATLAB代码

集合卡尔曼滤波(Ensemble Kalman Filter) 文章目录 引言理论基础卡尔曼滤波集合卡尔曼滤波初始化预测步骤更新步骤卡尔曼增益更新集合 MATLAB 实现运行结果3. 应用领域结论 引言 集合卡尔曼滤波(Ensemble Kalman Filter, EnKF)是…

解决Docker环境变量的配置的通用方法

我们部署的很多服务都是以Docker容器的形式存在的。 在运行Docker容器前,除了设置网络、数据卷之外,还需要设置各种各样的环境变量。 有时候,由于容器版本的问题,一些文档没有及时更新,可能同时存在多个新旧版本的环…

2446.学习周刊-2024年46周

封面 拍摄于11月17日,身心疲惫的时候,去山里走走看看风景,富氧的环境能缓解身心疲劳。 ✍优秀博文 # 深度解析数仓建模与指标体系构建的底层逻辑 | 金字塔原理在数仓建模分析中的应用基于“理采存管用”的数据中台建设方案业务逻辑不要放入…

自然语言处理:第六十三章 阿里Qwen2 2.5系列

本人项目地址大全:Victor94-king/NLP__ManVictor: CSDN of ManVictor 项目地址: QwenLM/Qwen2.5: Qwen2.5 is the large language model series developed by Qwen team, Alibaba Cloud. 官网地址: 你好,Qwen2 | Qwen & Qwen2.5: 基础模型大派对&a…

六、卷积神经网络(CNN)基础

卷积神经网络(CNN)基础 前言一、CNN概述二、卷积层2.1 卷积2.2 步幅(Stride)2.3 填充(Padding)2.4 多通道卷积2.5 多卷积计算2.6 特征图大小计算2.7 代码演示 三、池化层3.1 池化层计算3.1.1 最大池化层3.1.2 平均池化层 3.2 填充(Padding)3.3 步幅(Stri…

Spring Security SecurityContextHolder(安全上下文信息)

在本篇博客中,我们将讨论 Spring Security 的 SecurityContextHolder 组件,包括其实现方式、关键特性,并通过实际示例进行说明。 理解 SecurityContextHolder SecurityContextHolder 是 Spring Security 存储当前安全上下文详细信息的地方。…

通过vite+vue3+pinia从0到1搭建一个uniapp应用

最近项目上要做一个app,选择了用uniapp作为开发框架;我大概看了一下uniapp的文档,根据文档从0到1搭了一个uniapp应用供大家参考。 因为本人习惯使用了WebStorm编译器,但是uniapp官方推荐使用HBuilder搭建,如果和我一样…

【Pytorch】torch.nn.functional模块中的非线性激活函数

在使用torch.nn.functional模块时,需要导入包: from torch.nn import functional 以下是常见激活函数的介绍以及对应的代码示例: tanh (双曲正切) 输出范围:(-1, 1) 特点:中心对称,适合处理归一化后的数据…

java-贪心算法

1. 霍夫曼编码(Huffman Coding) 描述: 霍夫曼编码是一种使用变长编码表对数据进行编码的算法,由David A. Huffman在1952年发明。它是一种贪心算法,用于数据压缩。霍夫曼编码通过构建一个二叉树(霍夫曼树&a…

网络安全学习74天(记录)

11.21日,今天学习了 app抓包(需要的工具charles(激活),夜神模拟器,postern,) 思路:首先charles需要抓取的app的包,需要的是装证书,将charles的证…

【数据结构】【线性表】【练习】反转链表

申明 该题源自力扣题库19&#xff0c;文章内容&#xff08;代码&#xff0c;图表等&#xff09;均原创&#xff0c;侵删&#xff01; 题目 给你单链表的头指针head以及两个整数left和right&#xff0c;其中left<right&#xff0c;请你反转从位置left到right的链表节点&…