当前位置: 首页 > news >正文

MySQL主从复制(五):读写分离

一主多从架构主要应用场景:读写分离。读写分离的主要目标是分摊主库的压力。

读写分离架构


读写分离架构一

架构一结构图:

这种结构模式下,一般会把数据库的连接信息放在客户端的连接层,由客户端主动做负载均衡。也就是说由客户端来选择后端数据库进行查询。

读写分离架构二

架构二结构图:

该架构模式下,在MySQL和客户端之间有一个中间代理层proxy, 客户端只连接proxy, 由proxy根据请求类型和上下文决定请求的分发路由。

两种架构的区别

1)客户端直连方案

因为少了一层proxy转发, 所以查询性能稍微好一点儿, 并且整体架构简单, 排查问题更方便。 但是这种方案, 由于要了解后端部署细节, 所以在出现主备切换、 库迁移等操作的时候, 客户端都会感知到, 并且需要调整数据库连接信息。

你可能会觉得这样客户端也太麻烦了, 信息大量冗余, 架构很丑。 其实也未必, 一般采用这样的架构, 一定会伴随一个负责管理后端的组件, 比如Zookeeper, 尽量让业务端只专注于业务逻辑开发。

2)带proxy架构

带proxy的架构, 对客户端比较友好。 客户端不需要关注后端细节, 连接维护、 后端信息维护等工作, 都是由proxy完成的。 但这样的话, 对后端维护团队的要求会更高。 而且, proxy也需要有高可用架构。 因此, 带proxy架构的整体就相对比较复杂。

注:无论使用哪种架构都会遇到主从延迟问题(即在从库上会读到系统的一个过期状态),且主从延迟是不能100%避免的。

问:处理主从延迟有哪些方案?

答:主从延迟处理方案有以下几种:

  • 强制走主库方案
  • Sleep方案
  • 判断主备无延迟方案
  • 配合semi-sync方案
  • 等主库位点方案
  • 等GTID方案

下面对这几种方案详细介绍。

强制走主库方案


强制走主库方案思路:对查询请求进行分类,对于必须要拿到最新结果的请求,强制将其发到主库上。对于可以读到旧数据的请求,才将其发到从库上。

这个方案最大的问题在于, 有时候你会碰到“所有查询都不能是过期读”的需求, 比如一些金融类的业务。 这样的话, 你就要放弃读写分离, 所有读写压力都在主库, 等同于放弃了扩展性。

尽管如此,该方案仍是用的最多的一种方案。

Sleep方案


Sleep方案思路:主库更新后, 读从库之前先sleep一下。 具体的方案就是, 类似于执行一条select sleep(1)命令。

注:这个方案的假设是, 大多数情况下主备延迟在1秒之内, 做一个sleep可以有很大概率拿到最新的数据。

示例:

以卖家发布商品为例, 商品发布后, 用Ajax(Asynchronous JavaScript + XML, 异步JavaScript和XML) 直接把客户端输入的内容作为“新的商品”显示在页面上, 而不是真正地去数据库做查询。

这样, 卖家就可以通过这个显示, 来确认产品已经发布成功了。 等到卖家再刷新页面, 去查看商品的时候, 其实已经过了一段时间, 也就达到了sleep的目的, 进而也就解决了过期读的问题。

但从严格意义上来说,这个方案存在不精确问题。这个不精确主要包含两层意思:

1)假设一个查询请求原本可以在0.5s就可以在从库上拿到正确结果,此时也会等1s。

2)如果延迟超过1s,还是会出现主从延迟。

判断主备无延迟方案


确保备库无延迟,通常有以下三种做法:

查看seconds_behind_master确保主备无延迟

每次从库执行查询请求前,先执行show slave status\G判断seconds_behind_master是否已经等于0。 如果还不等于0 , 那就必须等到这个参数变为0才能执行查询请求。注:seconds_behind_master的单位是秒。show slave status\G结果的部分截图:

对比位点确保主备无延迟

1)Master_Log_File和Read_Master_Log_Pos, 表示的是读到的主库的最新位点。

2)Relay_Master_Log_File和Exec_Master_Log_Pos, 表示的是备库执行的最新位点。

如果Master_Log_File和Relay_Master_Log_File、 Read_Master_Log_Pos和Exec_Master_Log_Pos这两组值完全相同, 就表示接收到的日志已经同步完成。

show slave status\G结果部分截图:

对比GTID集合确保主备无延迟

1)Auto_Position=1 , 表示这对主备关系使用了GTID协议。

2)Retrieved_Gtid_Set, 是备库收到的所有日志的GTID集合。

3)Executed_Gtid_Set, 是备库所有已经执行完成的GTID集合。

如果这两个集合相同, 也表示备库接收到的日志都已经同步完成。

可见, 对比位点和对比GTID这两种方法, 都要比判断seconds_behind_master是否为0更准确。

show slave status\G结果部分截图:

问:在执行查询请求之前, 先判断从库是否同步完成的方法, 相比于sleep方案, 准确度确实提升了不少, 但还是没有达到“精确”的程度。 为什么这么说呢?

一个事务的binlog在主备库之间的状态:

1)主库执行完成, 写入binlog, 并反馈给客户端。

2)binlog被从主库发送给备库, 备库收到。

3)在备库执行binlog完成。

上面判断主备无延迟的逻辑, 是“备库收到的日志都执行完成了”。 但是, 从binlog在主备之间状态的分析中, 不难看出还有一部分日志, 处于客户端已经收到提交确认, 而备库还没收到日志的状态。

示例场景如下:

这时, 主库上执行完成了三个事务trx1、 trx2和trx3, 其中:

1)trx1和trx2已经传到从库, 并且已经执行完成了。

2)trx3在主库执行完成, 并且已经回复给客户端, 但是还没有传到从库中。

如果这时候你在从库B上执行查询请求, 按照我们上面的逻辑, 从库认为已经没有同步延迟, 但还是查不到trx3的。 严格地说, 就是出现了主从延迟。

配合semi-sync方案


该方案可以解决“对比GTID集合确保主备无延迟”中提到的不“精确”问题。

semi-sync replication(半同步复制)主备间的状态:

1)事务提交的时候,主库把binlog发给从库。

2)从库收到binlog后,给主库返回一个ack,表示收到了。

3)主库收到这个ack后,才能给客户端返回“事务完成”的确认。

也就是说,如果启用了semi-sync, 就表示所有给客户端发送过确认的事务, 都确保了备库已经收到了这个日志。

问1:如果主库掉电的时候,有些binlog还来不及发给从库,会不会导致系统数据丢失?

1)如果使用的是普通的异步复制模式,则有可能会丢失数据。

2)如果使用的是semi-sync+位点判断的方案,则可以解决数据丢失问题。

需要注意的是,semi-sync+位点判断的方案,只对一主一备的场景成立。在一主多从场景中,主库只要等到一个从库的ack,就会开始给客户端返回确认。此时,在从库上执行查询请求,有以下两种情况:

1)如果查询落在这个响应了ack的从库上,能够确保读到最新数据。

2)如果查询落到其它从库上,他们可能还没有收到最新的日志,就可能会产生主从延迟。

注:如果在业务高峰期, 主库的位点或者GTID集合更新很快, 那么上面的两个位点等值判断就会一直不成立, 很可能出现从库上迟迟无法响应查询请求的情况。

问2:当发起一个查询请求后,如果要求得到准确结果,是否需要等到“主备完全同步”,才能执行查询请求?

答:不需要。

示例如下:

图中备库B下的虚线框, 分别表示relaylog(备库执行的最新位点)和binlog中的事务。 可以看到, 图中从状态1 到状态4, 一直处于延迟一个事务的状态。

备库B一直到状态4都和主库A存在延迟, 如果用上面必须等到无延迟才能查询的方案, select语句直到状态4都不能被执行。

但是, 其实客户端是在发完trx1更新后发起的select语句, 我们只需要确保trx1已经执行完成就可以执行select语句了。 也就是说, 如果在状态3执行查询请求, 得到的就是预期结果了。

semi-sync+主备无延迟方案,存在两个问题:

1)一主多从的时候, 在某些从库执行查询请求会存在主从延迟问题。

2)在持续延迟的情况下, 可能出现过度等待的问题。

等主库位点方案


该方案能解决“semi-sync+主备无延迟方案”存在的两个问题。

下面先来看一条命令:

select master_pos_wait(file, pos[, timeout]);

这条命令的逻辑如下:

1)它是在从库执行的。

2)参数file和pos指的是主库上的文件名和位置。

3)timeout可选, 设置为正整数N表示这个函数最多等待N秒。

这条命令返回结果如下:

1)如果执行期间, 备库同步线程发生异常, 则返回NULL。

2)如果等待超过N秒, 就返回-1。

3)如果刚开始执行的时候, 就发现已经执行过这个位置了, 则返回0。

4)如果返回的是一个正整数M, 表示从命令开始执行, 到应用完file和pos表示的binlog位置, 执行了多少事务。

对于上图中先执行trx1, 再执行一个查询请求的逻辑, 要保证能够查到正确的数据, 我们可以使用这个逻辑:

1)trx1事务更新完成后, 马上执行show master status得到当前主库执行到的File和Position。

2)选定一个从库执行查询语句。

3)在从库上执行select master_pos_wait(File, Position, 1)。

4)如果返回值是>=0的正整数, 则在这个从库执行查询语句。

5)否则, 到主库执行查询语句。

上述逻辑流程图:

这里我们假设, 这条select查询最多在从库上等待1秒。 那么, 如果1秒内master_pos_wait返回一个大于等于0的整数, 就确保了从库上执行的这个查询结果一定包含了trx1的数据。

步骤5到主库执行查询语句, 是这类方案常用的退化机制(兜底方案)。 因为从库的延迟时间不可控, 不能无限等待, 所以如果等待超时, 就应该放弃, 然后到主库去查。

GTID方案


MySQL中同样提供了一个类似的命令:

select wait_for_executed_gtid_set(gtid_set, 1);

这条命令的逻辑是:

1)等待, 直到这个库执行的事务中包含传入的gtid_set, 返回0。

2)超时返回1。

在前面等位点的方案中, 我们执行完事务后, 还要主动去主库执行show master status。 而MySQL 5.7.6版本开始, 允许在执行完更新类事务后, 把这个事务的GTID返回给客户端, 这样等GTID的方案就可以减少一次查询。

等GTID的执行流程:

1)trx1事务更新完成后, 从返回包直接获取这个事务的GTID, 记为gtid1。

2)选定一个从库执行查询语句。

3)在从库上执行 select wait_for_executed_gtid_set(gtid1, 1)。

4)如果返回值是0, 则在这个从库执行查询语句。

5)否则, 到主库执行查询语句。

上述逻辑流程图:

问:怎么能够让MySQL在执行事务后, 返回包中带上GTID呢?

答:把参数session_track_gtids设置为OWN_GTID, 然后通过API接口mysql_session_track_get_first从返回包解析出GTID的值即可。

小结:思考题


思考:假设你的系统采用了等GTID的方案, 现在你要对主库的一张大表做DDL,在做读写分离时可能会出现什么情况呢? 为了避免这种情况, 你会怎么做呢?

假设,这条语句在主库上要执行10分钟,提交后传到备库就要10分钟(典型的大事务)。那么,在主库DDL之后再提交的事务的GTID,去备库查的时候,就会等10分钟才出现。

这样,这个读写分离机制在这10分钟之内都会超时,然后走主库。

这种预期内的操作,应该在业务低峰期的时候,确保主库能够支持所有业务查询,然后把读请求都切到主库,再在主库上做DDL。等备库延迟追上以后,再把读请求切回备库。

通过这个思考题,我主要想让关注的是,大事务对等位点方案的影响。

当然了,使用gh-ost方案来解决这个问题也是不错的选择。

相关文章:

MySQL主从复制(五):读写分离

一主多从架构主要应用场景:读写分离。读写分离的主要目标是分摊主库的压力。 读写分离架构 读写分离架构一 架构一结构图: 这种结构模式下,一般会把数据库的连接信息放在客户端的连接层,由客户端主动做负载均衡。也就是说由客户…...

阿里巴巴 EasyExcel 真正的高效与通用导入(亿级数据秒级导入)

需要lombok、hutool、alibaba EasyExcel 相关依赖包 基于Lamba表达式的通用监听器 import cn.hutool.core.util.StrUtil; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import lombok.experimental.UtilityClass…...

32.5k star!!替换 postman?【送源码】

在软件开发过程中,API(应用程序接口)扮演着至关重要的角色。为了确保 API 的可靠性和性能,开发人员需要一种高效的方式来测试和调试它们。这方面的工具,大家经常用到的应该就是 postman 了。不过,今天了不起…...

课时135:awk实践_逻辑控制_综合实践

1.3.8 综合实践 学习目标 这一节,我们从 网络实践、文件实践、小结 三个方面来学习 网络实践 简介 所谓的网络实践,主要是借助于awk的数组功能,进行站点的信息统计操作。准备网络环境 安装软件 yum install nignx -y重启nginx [rootloca…...

c++ 读取MNIST数据集实现softmax回归

pytorch教材 3.4. softmax回归 — 动手学深度学习 2.0.0 documentation c实现代码 代码太长了就没整理了&#xff0c;也暂时没有运行效果截图 同样没有本文也没有实现反向自动求导 超长代码警告&#xff0c;757行。不过可能注释占一半 #include <bits/stdc.h> usin…...

JS-04何为继承以及实现方式

目录 1 JS中继承的概念 2 为什么要使用继承&#xff1f;-解决内存浪费 2.1 问题引入 2.2 问题解决 2.3 拓展 3 继承的实现方式 3.1 原型链继承 1 3.2 原型链继承 2 1 JS中继承的概念 通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法&#xff0c;我们把这种…...

6款网站登录页(附带源码)

6款网站登录页 效果图及部分源码123456 领取源码下期更新预报 效果图及部分源码 1 部分源码 <style>* {margin: 0;padding: 0;}html {height: 100%;}body {height: 100%;}.container {height: 100%;background-image: linear-gradient(to right, #fbc2eb, #a6c1ee);}.l…...

spring boot打的包直接运行

Spring Boot 提供了一个插件 spring-boot-maven-plugin 把程序打包成一个可执行的jar包&#xff0c;直接执行java -jar xxx.jar即可以启动程序 1、引用 spring-boot-maven-plugin插件 <build><plugins><plugin><groupId>org.springframework.boot<…...

移除元素-力扣

第一种解法&#xff0c;暴力解法&#xff0c;使用两个for循环一个进行遍历&#xff0c;一个进行覆盖&#xff0c;代码如下&#xff1a; class Solution { public:int removeElement(vector<int>& nums, int val) {int size nums.size();for(int i 0; i < size; …...

代码随想录算法训练营第三天| 203.移除链表元素、 707.设计链表、 206.反转链表

203.移除链表元素 题目链接&#xff1a; 203.移除链表元素 文档讲解&#xff1a;代码随想录 状态&#xff1a;没做出来&#xff0c;做题的时候定义了一个cur指针跳过了目标val遍历了一遍链表&#xff0c;实际上并没有删除该删的节点。 错误代码&#xff1a; public ListNode re…...

【题解】AB33 相差不超过k的最多数(排序 + 滑动窗口)

https://www.nowcoder.com/practice/562630ca90ac40ce89443c91060574c6?tpId308&tqId40490&ru/exam/oj 排序 滑动窗口 #include <iostream> #include <vector> #include <algorithm> using namespace std;int main() {int n, k;cin >> n &…...

LSPatch免root手机模块应用

软件介绍 LSPatch是一款免root手机模块应用&#xff0c;兼容大部分机型&#xff0c;使用LSPatch&#xff0c;您可以个性化您的Android设备&#xff0c;添加新的功能&#xff0c;修改系统设置&#xff0c;甚至完全改变系统的外观。您可以根据自己的需求选择和安装各种Xposed模块…...

深入解析kube-scheduler的算法自定义插件

目录 ​编辑 一、问题引入 二、自定义步骤 三、最佳实践考虑 一、问题引入 当涉及到 Kubernetes 集群的调度和资源分配时&#xff0c;kube-scheduler 是一个关键组件。kube-scheduler 负责根据集群的调度策略&#xff0c;将 Pod 分配到适当的节点上。kube-scheduler 默认使…...

java原型模式 (Prototype Pattern) 介绍

原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它通过复制现有的实例来创建新对象&#xff0c;而不是通过实例化类来创建对象。这个模式允许你创建对象时避免复杂的初始化步骤&#xff0c;并且能够动态地创建对象的副本。 原型模式的关键…...

LLama3 | 一. 本地 Web Demo 部署

前置工作 课程文档&#xff1a;Llama3-Tutorial/docs/hello_world.md at main SmartFlowAI/Llama3-Tutorial GitHub 1.安装vscode 2.安装vscode插件 Remote SSH 3.配置 VSCode 远程连接开发机 ssh连接开发机 进行端口映射 在开发机控制台中点击自定义服务&#xff0c;复…...

MariaDB 给指定列值自动加密(持久数据加触发器)

文章目录 代码插入时&#xff0c;自动加密更新时&#xff0c;自动加密查看触发器数据操作示例update数据取出解密取 注意一次尝试&#xff0c;看加密后数据长度 参考链接&#xff1a; 一篇非常好的讲解触发器的文章&#xff1a;示例、原理MySQL/MariaDB触发器。 用触发器自动加…...

深入理解Linux系统管理与网络配置高级指南

深入理解Linux系统管理与网络配置高级指南 目录 深入理解Linux系统管理与网络配置高级指南 一、Linux文件系统管理 二、Linux进程管理 三、Linux系统管理 四、Linux网络管理 五、Linux磁盘管理 一、Linux文件系统管理 1.1 文件和目录操作 在Linux中&#xff0c;一切皆…...

朴素贝叶斯+SMSSpamCollections

1. 打开 Jupyter 后&#xff0c;在工作目录中&#xff0c;新建一个文件夹命名为 Test01 &#xff0c;并且在文件夹中导入数据 集。在网页端界面点击 “upload” 按钮&#xff0c;在弹出的界面中选择要导入的数据集。然后数据集出现 在 jupyter 文件目录中&#xff0c;此时…...

【Android Studio】使用UI工具绘制,ConstraintLayout 限制性布局,快速上手

文章目录 一、前言二、绘制效果三、ConstraintLayout 使用方法3.1 创建布局文件3.2 替换配置3.3 设置约束&#xff0c;步骤13.4 设置约束&#xff0c;步骤23.5 其他设置 四、结束 一、前言 在进行Android APP开发过程中&#xff0c;减少layout嵌套即可改善UI的绘制性能&#x…...

深度神经网络详解

深度神经网络详解 一、引言二、深度神经网络的基本概念1. 什么是神经网络2. 深度神经网络的定义3. 基本结构4. 激活函数 三、深度神经网络的发展历史1. 初期发展2. 反向传播算法的提出3. 深度学习的崛起 四、深度神经网络的架构1. 前馈神经网络&#xff08;Feedforward Neural …...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...