一:读写分离

  - 概念

    -  读写分离的主要目标就是分摊主库的压力。

  - 基本架构

    -     - 

二:两种读写分离的架构特点

  - 客户端直连方案

    - 因为少了一层 proxy 转发,所以查询性能稍微好一点儿,并且整体架构简单,排查问题更方便。

    - 但是这种方案,由于要了解后端部署细节,所以在出现主备切换、库迁移等操作的时候,客户端都会感知到,并且需要调整数据库连接信息。

    - 你可能会觉得这样客户端也太麻烦了,信息大量冗余,架构很丑。

    - 其实也未必,一般采用这样的架构,一定会伴随一个负责管理后端的组件,比如 Zookeeper,尽量让业务端只专注于业务逻辑开发。

  - proxy 方案

    - 带 proxy 的架构,对客户端比较友好。客户端不需要关注后端细节,连接维护、后端信息维护等工作,都是由 proxy 完成的。

    - 但这样的话,对后端维护团队的要求会更高。而且,proxy 也需要有高可用架构。

    - 因此,带 proxy 架构的整体就相对比较复杂。

三:什么是“过期读” ?

  -  “在从库上会读到系统的一个过期状态”的现象,暂且称之为“过期读”。

四:处理 “过期读” 的方案?

  - 强走主库方案

  - sleep 方案;

  - 判断主备无延迟方案;

  - 配合 semi-sync 方案;

  - 等主库位点方案;

  - 等 GTID 方案。

五:强走主库方案

  - 原理

    - 强制走主库方案其实就是,将查询请求做分类。

    - 对于必须要拿到最新结果的请求,强制将其发到主库上。

      - 比如,在一个交易平台上,卖家发布商品以后,马上要返回主页面,看商品是否发布成功。

      - 那么,这个请求需要拿到最新的结果,就必须走主库。

    - 对于可以读到旧数据的请求,才将其发到从库上。

      -  在这个交易平台上,买家来逛商铺页面,就算晚几秒看到最新发布的商品,也是可以接受的。那么,这类请求就可以走从库。

  - 问题

    - 这个方案最大的问题在于,有时候你会碰到“所有查询都不能是过期读”的需求,比如一些金融类的业务。

    - 这样的话,你就要放弃读写分离,所有读写压力都在主库,等同于放弃了扩展性。

六:sleep 方案

  - 原理

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

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

      - 如如在客户端在下单完成后做1s的loading,其实等于变相的等待了从库1s。

  - 问题

    - sleep 方案确实解决了一定场景下的过期读问题。

    - 但,从严格意义上来说,这个方案存在的问题就是不精确。

    - 这个不精确包含了两层意思:

      - 如果这个查询请求本来 0.5 秒就可以在从库上拿到正确结果,也会等 1 秒;

      - 如果延迟超过 1 秒,还是会出现过期读。

七:判断主备无延迟方案

  - 原理

    - 通过 show slave status;结果

    - 

  - 对比  seconds_behind_master 判断主备无延迟(精度S)

    - 每次从库执行查询请求前,先判断 seconds_behind_master 是否已经等于 0。

    - 如果还不等于 0 ,那就必须等到这个参数变为 0 才能执行查询请求。

  - 对比 点位 判断主备无延迟

    -  Master_Log_File 和 Read_Master_Log_Pos,表示的是读到的主库的最新位点;

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

    -  如果

      - Master_Log_File == Relay_Master_Log_File

      - Read_Master_Log_Pos == Exec_Master_Log_Pos

      - 这两组值完全相同,就表示接收到的日志已经同步完成。

  - 对比  GTID 判断主备无延迟

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

    - Retrieved_Gtid_Set,是备库收到的所有日志的 GTID 集合;

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

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

  - 小结

    - 虽然等待无延迟是可以解决问题,但是可能存在主备一直不一致,导致备库无法读取的问题。

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

    - 这几种办法并没有达到 “精确” 的程度,可能存在 主库已经执行,但是还没有发送给备库的情况,导致过期读。(通过 semi-sync 解决)

八: 等主库点位方案 / 等GTID方案

  - 这两个方案都是 在备库执行,等待一定时间,如果在时间内 主库点位 / GTID 同步,则在备库执行,否则到主库执行。

九:小结

  - 这几种方案中,有的方案看上去是做了妥协,有的方案看上去不那么靠谱儿,但都是有实际应用场景的,你需要根据业务需求选择。

  - 即使是最后等待位点和等待 GTID 这两个方案,虽然看上去比较靠谱儿,但仍然存在需要权衡的情况。

    - 如果所有的从库都延迟,那么请求就会全部落到主库上,这时候会不会由于压力突然增大,把主库打挂了呢?

  - 其实,在实际应用中,这几个方案是可以混合使用的。

  - 比如,先在客户端对请求做分类,区分哪些请求可以接受过期读,而哪些请求完全不能接受过期读;然后,对于不能接受过期读的语句,再使用等 GTID 或等位点的方案。

  - 但话说回来,过期读在本质上是由一写多读导致的。

  - 在实际应用中,可能会有别的不需要等待就可以水平扩展的数据库方案,但这往往是用牺牲写性能换来的,也就是需要在读性能和写性能中取权衡。

《Mysql - 读写分离有哪些坑?》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. Linux下的find命令详解

    0x01 简介 find命令用来在指定目录下查找文件.任何位于参数之前的字符串都将被视为欲查找的目录名.如果使用该命令时,不设置任何参数,则find命令将在当前目录下查找子目录与文件.并且将查找到的子 ...

  2. OpenCV Facial Landmark Detection 人脸关键点检测

    Opencv-Facial-Landmark-Detection 利用OpenCV中的LBF算法进行人脸关键点检测(Facial Landmark Detection) Note: OpenCV3.4 ...

  3. Guided Hacking DLL Injector 3.3

    Guided Hacking DLL Injector 3.3 https://guidedhacking.com/resources/guided-hacking-dll-injector.4/ I ...

  4. 制作 python解释器

    https://www.zhihu.com/tardis/sogou/qus/27286136

  5. C#利用反射获取实体类的主键名称或者获取实体类的值

    //获取主键的 PropertyInfo PropertyInfo pkProp = ).FirstOrDefault(); //主键名称 var keyName=pkProp.Name; //实体类 ...

  6. Java获取系统基础参数信息

    一.JVM已经帮我们读取了系统信息 public void testSystemParam(){ Properties p = System.getProperties(); Iterator it ...

  7. 品优购商城项目(二)AngularJS、自动代码生成器、select2下拉多选框

    品优购商城想项目第二阶段 AngularJS.自动代码生成器.select2下拉多选框 完成了课程第三天.第四天的的任务. 1.学习了AngularJs前端的mvc分层思想,js部分分成control ...

  8. Flutter Navigator&Router(导航与路由)

    参考地址:https://www.jianshu.com/p/b9d6ec92926f 在我们Flutter中,页面之间的跳转与数据传递使用的是Navigator.push和Navigator.pop ...

  9. 泡泡一分钟:Aided Inertial Navigation: Unified Feature Representations and Observability Analysis

    http://udel.edu/~yuyang/downloads/tr_observabilityII.pdf Aided Inertial Navigation: Unified Feature R ...

  10. Spring cloud微服务安全实战-6-2JWT认证之认证服务改造

    首先来解决认证的问题. 1.效率低,每次认证都要去认证服务器调一次服务. 2.传递用户身份,在请求头里面, 3.服务之间传递请求头比较麻烦. jwt令牌. spring提供了工具,帮你在微服务之间传递 ...