当前位置: 首页 > 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 …...

MYSQL 数据迁移利器 MYSQLSH

1 迁移背景 将数据库从mysql5.7 迁移到mysql8.0. mysqlsh 支持mysql5.7以上版本。 2 查看数据量 SELECT TABLE_SCHEMA, round(SUM(data_length+index_length)/1024/1024,2) AS TOTAL_MB, round(SUM(data_length)/1024/1024,2) AS DATA_MB, …...

【MYSQL】分数排名

表: Scores ---------------------- | Column Name | Type | ---------------------- | id | int | | score | decimal | ---------------------- id 是该表的主键&#xff08;有不同值的列&#xff09;。 该表的每一行都包含了一场比赛的分数。Score 是…...

【论文笔记】| 蛋白质大模型ProLLaMA

【论文笔记】| 蛋白质大模型ProLLaMA ProLLaMA: A Protein Large Language Model for Multi-Task Protein Language Processing Peking University Theme: Domain Specific LLM Main work&#xff1a; 当前 ProLLM 的固有局限性&#xff1a;&#xff08;i&#xff09;缺乏自然…...

MySQL笔记第一天(从小白到入门)

文章目录 MySQL笔记SQL语言介绍数据库系统关系型数据库非关系型数据库SQL和数据库系统的关系数据库系统架构 MySQL的介绍概念MySQL的版本 MySQL的DDL操作-重点基本数据库操作基本表操作 MySQL的DML操作-重点insert-插入数据update-更新数据delete-删除数据 MySQL的约束-了解概述…...

初识Qt:从Hello world到对象树的深度解析

Qt中的对象树深度解析 Hello world1.图形化界面创建命令行式创建在栈上创建在堆上创建为什么传文本需要QString&#xff0c;std::string不行吗&#xff1f;那为什么要传入this指针&#xff1f;为什么new后不用显示调用delete函数呢&#xff0c;不会造成内存泄漏问题吗&#xff…...

多维数据库创建

多维数据库 小白的数据仓库学习笔记 2024/5/21 上午 文章目录 多维数据库Cube的作用&#xff1a;什么是多维数据库维的级别多维数据分析方法如何构建多维数据集&#xff1f;创建项目创建数据源创建数据源视图创建多维数据集维度表中缺失的值拖拽过去建立维度结构设计类型启动连…...

win11安装docker运行Open-Webui 界面化展示 ollama大模型

1.OpenWeb UI运行需要docker 环境下载docker Get Started | Docker 2.需要命令提示符docker -v 查询是否安装成功&#xff1b; 查询docker详情docker version 3.github拉取open-webUi镜像Package open-webui GitHub 复制命令运行在命令提示符&#xff1b; 等待下载完成 4.到…...

网络模型-PoE技术

一、PoE简介 以太网供电PoE(Powerover Ethernet)是指通过以太网网络进行供电&#xff0c;也被称为基于局域网的供电系统PoL(PoweroverLAN)或有源以太网(Active Ethernet)。 1、PoE的优势: 可靠: 电源集中供电&#xff0c;备份方便。连接简捷: 网络终端不需外接电源&#xf…...

网站策划是什么

网站策划是指在建立、设计和运营一个网站时所采取的系统性规划和组织活动。它涵盖了从确定网站的目标和目标受众到确定内容、功能、设计和营销策略等方面的各个方面。在今天互联网时代的背景下&#xff0c;网站已经成为企业、组织和个人展示自身形象、提供信息和服务、开展交流…...

MySQL基础学习: SET FOREIGN_KEY_CHECKS = 0

文章目录 一、介绍二、使用方法三、注意事项 一、介绍 在MySQL中&#xff0c;SET FOREIGN_KEY_CHECKS 0; 是一个特殊的命令&#xff0c;用于临时禁用外键约束检查。这在你执行一些涉及多个表并且可能违反外键约束的批量操作时非常有用。 为什么需要禁用外键约束检查&#xf…...