Mysql读写分离的过期读问题

在数据库高可用架构中,读写分离是提升系统吞吐量的核心手段。其基本逻辑是:主库(Master)负责所有写入操作,从库(Slave)分担查询压力。然而,由于主从同步存在物理延迟,客户端可能在备库读到尚未同步的旧数据,这种现象被称为"过期读" 。

一、 读写分离的实现架构

实现读写分离主要有两种主流方案:

  1. 客户端直连 (Client-side)
  • 执行逻辑:应用代码内部实现负载均衡,配置主库和多个从库的 IP,根据请求类型分发。
  • 特点:性能损耗极低,架构简单;但运维成本高,主备切换时需要修改所有客户端配置 。
  1. 带 Proxy 的中间件架构 (Proxy-side)
  • 执行逻辑:应用只连接 Proxy,由 Proxy 负责 SQL 解析、路由分发和后端存活检测。
  • 特点:对应用透明,运维方便;但增加了网络延迟,且 Proxy 自身需要考虑高可用 。

二、 解决"过期读"的六种方案

为了在提升性能的同时保证数据准确,需要针对不同业务场景选择合适的"过期读"解决方案。

  1. 强制走主库方案
  • 策略:将查询请求分为"允许延迟"和"必须实时"两类。
  • 示例:用户刚修改完个人资料,其"个人中心"页面必须强制查主库以保证可见性;而其他用户浏览该资料时可走备库。
  1. Sleep 方案
  • 策略 :在写操作后,读操作前让客户端执行一次短时间的 sleep
  • 评价:这是一种不严谨的概率性方案。如果延迟超过 sleep 时间,依然会读到旧数据;反之则会浪费响应时间。
  1. 判断主备延迟方案
  • 在查询备库前,先通过以下方式确认同步进度:
    • 监控 SBM :确保 seconds_behind_master 为 0。
    • 对比位点 :确保已收到的日志位点 Read_Master_Log_Pos 等于已执行位点 Exec_Master_Log_Pos
    • 对比 GTID 集合 :确保备库已执行的集合 Executed_Gtid_Set 包含已收到的集合 Retrieved_Gtid_Set
  1. 配合半同步复制 (Semi-Sync) 方案
  • 策略:利用半同步复制保证主库返回成功前,至少有一个备库收到了 binlog。
  • 配合:结合"对比位点"法。只要备库收到的位点等于主库最新的位点,代表数据已到。
  • 局限:在一主多从架构下,如果请求落到了那个恰好没收到日志的备库,方案会失效 。
  1. MASTER_POS_WAIT 等位点方案
  • 物理流程
    1. 写操作完成后,通过 SHOW MASTER STATUS 获取主库当前的 FilePosition
    2. 客户端去备库执行 SELECT MASTER_POS_WAIT(File, Position, timeout)
    3. 如果函数返回 ≥0\ge 0≥0,说明备库已追平该点,可以安全读取。
  1. WAIT_FOR_EXECUTED_GTID_SET 等 GTID 方案
  • 这是目前最先进且精确的方案,基于 MySQL 5.7+ 的 GTID 机制
  • 物理流程
    1. 主库写入成功后返回该事务的 gtid 给客户端。
    2. 客户端去备库执行 SELECT WAIT_FOR_EXECUTED_GTID_SET(gtid, timeout)
    3. 备库会阻塞等待,直到该 GTID 被本地执行完成。
  • 优化 :设置 session_track_gtids=OWN_GTID,主库会在响应报文里自动带上最新的 GTID,简化开发逻辑 。
相关推荐
2401_824697661 小时前
CSS如何实现元素反转特效_使用transform-scaleX(-1)操作
jvm·数据库·python
皮皮学姐分享-ppx1 小时前
上市公司数字技术风险暴露数据(2010-2024)|《经济研究》同款大模型测算
大数据·网络·数据库·人工智能·chatgpt·制造
CLX05051 小时前
如何在 WordPress AMP 网站中为特定模板禁用 AMP 渲染
jvm·数据库·python
神明9312 小时前
如何实现SQL动态字段选择查询_利用反射或动态拼接字符串
jvm·数据库·python
m0_733565462 小时前
golang如何实现RabbitMQ死信队列_golang RabbitMQ死信队列实现教程
jvm·数据库·python
weixin_444012932 小时前
CSS定位如何实现模态框垂直居中_使用负边距或transform
jvm·数据库·python
2301_783848652 小时前
Go 中实现高效图最大团划分的实践与边界分析
jvm·数据库·python
2401_884454152 小时前
C#怎么实现Socket心跳包 C#如何在TCP Socket通信中设计心跳机制检测连接状态【网络】
jvm·数据库·python
Jetev2 小时前
不同品牌SSD对HTML函数工具加载速度影响大吗_存储测试汇总【汇总】
jvm·数据库·python