一:读写分离

  - 概念

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

  - 基本架构

    -     - 

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

  - 客户端直连方案

    - 因为少了一层 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. Windows 实例远程桌面报错“没有远程桌面授权服务器可以提供许可证”

    参考阿里云帮助文档: https://help.aliyun.com/knowledge_detail/40859.html?spm=5176.10695662.1996646101.searchcl ...

  2. DELPHI LINUX中间件隆重发布

    LINUX和WINDOWS是目前最流利的两个服务器操作系统,各种云服务商也是同时提供这2种操作系统的云服务器. 即日起,在原有WINDOWS中间件的产品基础上,再隆重推出新产品:LINUX中间件.这样 ...

  3. js的prototype理解

    转载:https://www.cnblogs.com/douyage/p/8630529.html 在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实 ...

  4. java判断A字符串中是否包含B字符

    java.lang.String类提供的方法 public boolean contains(CharSequence s) 当且仅当此字符串包含指定的 char 值序列时,返回 true. 例如: ...

  5. 【Java.Regex】用正则表达式查找Java文件里的字符串

    代码: import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; imp ...

  6. 用java输出杨辉三角

    杨辉三角:它的两个边都是1,内部其它都是肩上两个数的和 第一种: package aaa; public class YangHui { public static void main(String[ ...

  7. 从内核3.7版本开始,Linux就开始支持VXLAN 到了内核3.12版本,Linux对VXLAN的支持已经完备,支持单播和组播,IPv4和IPv6。

    一.关于VXLAN VXLAN 是 Virtual eXtensible LANs 的缩写,它是对 VLAN 的一个扩展,是非常新的一个 tunnel 技术,在Open vSwitch中应用也非常多. ...

  8. Github: 提升Github下载速度

    通过修改hosts文件来提速(该方法也可加速其他因为CDN被屏蔽导致访问慢的网站) 第一步:获取GitHub的IP地址 通过访问:http://tool.chinaz.com/dns或者https:/ ...

  9. java使用json-lib库的json工具类.

    import net.sf.ezmorph.object.DateMorpher;import net.sf.json.JSONArray;import net.sf.json.JSONObject; ...

  10. Tomcat 目录结构以及相关规范的介绍

    目录 安装tomcat tomcat目录结构 tomcat/bin目录 tomcat/conf目录 tomcat/logs目录 JavaEE对项目结构的规范 war包 安装Tomcat 参考:安装Ja ...