初学MySQL—读写分离

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ghw15221836342/article/details/100008428

概述

读写分离基本结构
读写分离的主要目标是分摊主库的压力,上图的结构是客户端主动做负载均衡,由客户端来选择后端数据进行查询;

另一种架构是MySQL和客户端之间有一个中间代理层proxy,客户端只连接proxy,由proxy根据请求类型和上下文决定请求的分发路由。
proxy读写分离结构
两种方案:

客户端直连方案:
查询性能好一点,整体架构简单便于排查问题。但尽心主备切换、库迁移等需要调整客户端连接信息,需要伴随一个负载管理后端的组件,例如Zookeeper,尽量让业务端只专注于业务逻辑开发;

proxy架构
对客户端比较友好。客户端不需要关注后端细节,连接维护、后端信
息维护等工作,都是由 proxy 完成的。但这样的话,对后端维护团队的要求会更高。而
且,proxy 也需要有高可用架构。

但是两种方案都可能会有一个问题,就是"过期读"
由于主从可能存在延迟,客户端执行完一个更新事务后马上发起查询,如果查询选择的是从库的话,就有可能读到刚刚的事务更新之前的状态

下面是解决过期读的一些方案。

  • 强制走主库方案
  • sleep方案
  • 判断主备无延迟方案
  • 配合semi-sync方案
  • 等GTID方案

强制走主库方案

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

  1. 对于必须要拿到最新结果的请求,强制将其发到主库上;例如,交易平台上卖家发布商品之后,马上返回主界面查看商品是否发布成功,这个请求需要拿到最新的结果,必须走主库;
  2. 对于可以读到旧数据的请求,才将其发到从库上;比如,买家逛商铺页面,晚几秒看到新发布的商品也是可以接受的;

Sleep方案

主库更新后,读从库前先sleep一下,大多数情况下主备延迟在一秒内,做个sleep可以有很大概率拿到最新的数据;

以卖家发布商品为例,商品发布后,用 Ajax(Asynchronous JavaScript + XML,异步
JavaScript 和 XML)直接把客户端输入的内容作为“新的商品”显示在页面上,而不是真
正地去数据库做查询。

卖家就可以通过这个显示,来确认产品已经发布成功了。等到卖家再刷新页面,去
查看商品的时候,其实已经过了一段时间,也就达到了 sleep 的目的,进而也就解决了过期读的问题。

判断主备无延迟方案

要确保备库无延迟,通常有三种做法:

  1. 确保主备无延迟,每次从库执行查询请求前,先判断
    seconds_behind_master 是否已经等于 0,等到该值为0才能执行查询请求;

  2. 对比位点确保主备无延迟;

  3. 对比GTID确保主备无延迟
    GTID:全称是 Global Transaction Identifier,也就是全局事务 ID,是一个事务在提交的时候生成的,是这个事务的唯一标识。

    Auto_Position=1 ,表示这对主备关系使用了 GTID 协议。
    Retrieved_Gtid_Set,是备库收到的所有日志的 GTID 集合;
    Executed_Gtid_Set,是备库所有已经执行完成的 GTID 集合

配合semi-sync

引入半同步复制,也就是 semi-sync replication
设计如下:

  1. 事务提交的时候,主库把 binlog 发给从库;
  2. 从库收到 binlog 以后,发回给主库一个 ack,表示收到了;
  3. 主库收到这个 ack 以后,才能给客户端返回“事务完成”的确认。

如果启用了semi-sync,表示所有给客户端发送过确认的事务,都确保了备库已经收到了这个日志。

等GTID方案

如果你的数据库开启了GTID方案,对应的也有等待GTID的方案

select wait_for_executed_gtid_set(gtid_set, 1);

这个命令的逻辑是:

  1. 等待,直到这个库执行的事务中包含传入的 gtid_set,返回 0;
  2. 超时返回 1;

GTID的执行流程如下:

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

wait_for_executed_gtid_set 方案

总结

本文介绍了读写分离,一主多从,可能会遇到过期读的问题,以及相关的解决方案;

文章创建于:
展开阅读全文

没有更多推荐了,返回首页