• Mysql 45讲学习笔记(二十八)读写分离


    一.读写分离的两种模式

    1、客户端(client)主动做负载均衡

     2.mysql通过中间代理层proxy 根据请求类型和上下文决定请求的分发路由

     客户端直连和带proxy的读写分离架构

    • 客户端直连方案,查询性能好,但是需要了解后端部署细节
    • 主备切换,库迁移等操作客户端都会感知,需要调整数据库连接信息
    • 、这样客户端麻烦,信息大量冗余,架构丑
    • 一定会伴随着管理后端的组件,Zookeeper,后端专注业务逻辑开发

    proxy架构

    • 对客户端友好,客户端不需要感知后端细节,连接维护,后端信息维护等工作都是proxy完成

    二.过期读

         从库会读到系统的过期状态

    三.强制走主库方案

    将查询请求分类:

    • 对于必须要拿到最新结果的请求,强制其发到主库上 
    • 对于可以读到旧数据的请求,才将其发到从库上

    四.Sleep方案

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

    最佳实践:

    • 以卖家发布商品为例,商品发布后,Ajax(Asynchronous JavaScript + XML,异步 JavaScript 和 XML)直接把客户端输入的内容作为"新商品"显示在页面上,不会真正进行数据库查询
    • 卖家直接通过显示来确认产品发布成功,等卖家再去看看的时候就达到了sleep的目的,解决过期读的问题

    存在问题:

    • 如果这个查询请求本来0.5就可以从库拿到正确结果,也会等1s    
    • 如果延迟超过1s,也会出现过期读
       

    五.判断主备无延迟方案

    1. 每次从库执行查询请求前,先判断 seconds_behind_master 是否已经等于 0。如果还不等于 0,那就必须等到这个参数变为 0 才能执行查询请求。
    2. 对比位点确保主备无延迟

    六.配合 semi-sync(半同步复制)------增加确认状态

    semi-sync 设计原理:

    • 事务提交的时候,主库将binlog发给从库
    • 从库收到binlog后,发给主库一个ack,表示收到了
    • 主库收到ack以后,才给客户端返回"事务完成"确认

    semi-sync+ 位点判断的方案存在问题:

    • 只会一主一备场景,在一主多从场景,主库只要等到一个从库的ack,就开始给客户端返回确认
    • 如果查询落到其他从库上,就导致过期读

    最严重的问题

            业务更新的高峰期,主库的位点或者GITD集合更新很快,导致等值判断一直不成立,从库迟迟无法响应查询请求的问题

    七.等主库位点方案

       

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

         返回正整数M。表示命令执行开始,到应用file和pos的binlog位置,执行了多少事务

    • 如果执行期间,备库同步线程发生异常,则返回NULL
    • 如果等待超过N秒,就返回-1;
    • 刚开始执行的时候,发现已经执行过这个位置,就返回0

    根据该命令执行的优化方案流程:

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

    选定一个从库执行查询语句;

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

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

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

    1. trx1事务更新完成后,马上执行show master status得到当前主库执行的File和Position
    2. 选定一个从库执行查询语句
    3. 在从库上执行select master_pos_wait(File, Position, 1);
    4. 如果返回值>=0,则在从库执行查询语句
    5. 否则到主库执行查询语句    

    八.GTID 方案

        

    select wait_for_executed_gtid_set(gtid_set,1);
    • 等待,直到这个库执行的事务中包含传入的gtid_set,返回0;
    • 超时返回1

    优化后的执行方案:

    • trx1事务更新完成后,从返回包直接获取这个事务 的GTID,记为gtid1
    • 选定一个从库执行查询语句
    • 在从库执行select wait_for_executed_gtid_set(gtid1, 1)
    • 如果返回值是0,则在这个从库执行查询语句
    • 否则到主库执行查询语句

  • 相关阅读:
    php7.3 centos7.9安装sqlserver扩展
    构建 dotnet&vue 应用镜像->推送到 Nexus 仓库->部署为 k8s 服务实践
    刷题笔记day27-回溯算法1
    转发和重定向的区别及使用场景
    AI | 第5章 深度学习 TensorFlow2 神经网络与卷积神经网络
    虚拟机Linux如何做快照、备份以及快照的使用
    Unity入门06——Unity重要组件和API(3)
    【REACT中setState回调函数(何时更新DOM)】
    Linux 下安装python
    JavaScript:js实现在线五子棋人机(人人)对弈
  • 原文地址:https://blog.csdn.net/weixin_42369687/article/details/126131240