一:读写分离

  - 概念

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

  - 基本架构

    -     - 

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

  - 客户端直连方案

    - 因为少了一层 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. Android中活动被回收了怎么办

    当一个活动进入到了停止状态,是有可能被系统回收的.按下返回键的时候,活动被重新创建一次,但是里面的数据就没办法重现: 这时Activity中提供了一个onSaveInstanceState()回调方法 ...

  2. windows--zabbix-agent添加主机

        1.首先在 C 盘根目录下创建 zabbix 的文件夹 2.将需要的文件拖到该文件夹内(bin/win64) 3.修改 windows 配置文件(zabbix.agent.win.conf)的 ...

  3. mac使用poetry

    安装 为了防止依赖冲突不推荐使用pip的方式直接安装,当然你也可以这样做 curl -sSL https://raw.githubusercontent.com/sdispater/poetry/ma ...

  4. Sequence contains no elements

    这个错误,在使用List<T>的First函数遇到. Sequence contains no elements? From "Fixing LINQ Error: Sequen ...

  5. 【转】php7+IIS 配置环境(windows环境)

    继php7+apache2.4 配置环境(window环境)后,由于B2C项目准备上线:特此小编在阿里云上搭建PHP7环境,为此特写上搭建过程希望正处于搭建php7+IIS(windows环境)中的朋 ...

  6. [V5] ARM: dts: Change i2s compatible string on exynos5250【转】

    本文转载自:https://patchwork.kernel.org/patch/2845464/ Padmavathi VennaAug. 16, 2013, 4:26 a.m. UTC This ...

  7. 文献阅读 | Resetting histone modifications during human parental-to-zygotic transition

    Resetting histone modifications during human parental-to-zygotic transition 人类亲本-合子转变中组蛋白修饰重编程 sci-h ...

  8. 用sublime cmd 快速打开hosts文件

      :: notepad start subl "%systemdrive%\WINDOWS\system32\drivers\etc\hosts"     文章来源:刘俊涛的博客 ...

  9. 【转】IDEA新建项目时,没有Spring Initializr选项(亲测有效)

    最近开始使用IDEA作为开发工具,然后也是打算开始学习使用spring boot.看着博客来进行操作上手spring boot,很多都是说创建一个新项目(Create New Project) 选择 ...

  10. pip 安装,更新模块

    moudle_name:是对应的模块名:请自行更换为自己需要更新的模块名 查看所有可更新的模块: pip list --outdated 更新某一个模块: pip install --upgrade ...