MySQL读写分离

读写分离是提升 MySQL 并发的首选方案,当单台 MySQL 无法满足要求时,就只能用多个具有相同数据的 MySQL 实例组成的集群来承担大量的读写请求。

把 MySQL 集群拆分成“主 + 从”结构的数据集群,这样才能实现程序上的读写分离,并且 MySQL 集群的主库、从库的数据是通过主从复制实现同步的。

1. MySQL主从复制的原理

MySQL 的主从复制依赖于 binlog ,记录 MySQL 上的所有变化并以二进制形式保存在磁盘上。将 binlog 中的数据从主库传输到从库上。这个过程一般是异步的,主库上执行事务操作的线程不会等待复制 binlog 的线程同步完成。MySQL 集群的主从复制过程分为 3 个阶段。

  • 写入 Binlog:主库写 binlog 日志,提交事务,并更新本地存储数据。
  • 同步 Binlog:把 binlog 复制到所有从库上,每个从库把 binlog 写到暂存日志中。
  • 回放 Binlog:回放 binlog,并更新存储数据。

主从复制过程:

  • MySQL 主库在收到客户端提交事务的请求之后,会先写入 binlog,再提交事务,更新存储引擎中的数据,事务提交完成后,返回给客户端“操作成功”的响应。
  • 从库会创建一个专门的 I/O 线程,连接主库的 log dump 线程,来接收主库的 binlog 日志,再把 binlog 信息写入 relay log 的中继日志里,再返回给主库“复制成功”的响应。
  • 从库会创建一个用于回放 binlog 的线程,去读 relay log 中继日志,然后回放 binlog 更新存储引擎中的数据,最终实现主从的数据一致性。

完成主从复制之后,可以在写数据时只写主库,读数据时只读从库,这样即使写请求会锁表或者锁记录,也不会影响读请求的执行。

MySQL一主多从:

读流量比较大时,部署多个从库共同承担读流量,就是“一主多从”的部署方式,垂直电商项目中可以用该方式抵御较高的并发读流量。另外,从库也可以作为一个备库,以避免主库故障导致的数据丢失。

从库数量增加,从库连接上来的 I/O 线程也比较多,主库也要创建同样多的 log dump 线程来处理复制的请求,对主库资源消耗比较高,同时还受限于主库的网络带宽。实际使用中,一个主库一般跟 2~3 个从库(1 套数据库,1 主 2 从 1 备主),这就是一主多从的 MySQL 集群结构。

MySQL 默认是异步模式:MySQL 主库提交事务的线程并不会等待 binlog 同步到各从库,就返回客户端结果。这种模式一旦主库宕机,数据就会发生丢失。

MySQL 主从复制还有哪些模型?

  • 同步复制:事务线程要等待所有从库的复制成功响应。
  • 异步复制:事务线程完全不等待从库的复制成功响应。
  • 半同步复制:MySQL 5.7 版本之后增加的一种复制方式,只要一部分复制成功响应回来就行,比如一主二从的集群,只要数据成功复制到任意一个从库上,主库的事务线程就可以返回给客户端。

半同步复制的方式,兼顾了异步复制和同步复制的优点,即使出现主库宕机,至少还有一个从库有最新的数据,不存在数据丢失的风险。

2. 解决主从复制的延迟问题

从架构上解决主从复制延迟:

问题案例:

电商平台,每次用户发布商品评论时,会先调用评论审核,对用户发布的商品评论进行如言论监控、图片鉴黄等操作。评论更新完主库后,异步调用审核模块,把评论ID传递给审核模块,审核模块用评论ID在从库中获取完整的评论信息。主从数据库存在延迟,从库还没有将信息复制过来,整个流程就出现了异常。

解决方案:

  • 使用数据冗余:

在异步调用审核模块时,不仅仅发送商品 ID,而是发送审核模块需要的所有评论信息,借此避免在从库中重新查询数据。但要注意每次调用的参数大小,过大的消息会占用网络带宽和通信时间。

  • 使用缓存解决:

在写入数据主库的同时,把评论数据写到 Redis 缓存里,这样其他线程再获取评论信息时会优先查询缓存,也可以保证数据的一致性。

该方式存在缓存和数据不一致性问题,线程 A 先更新数据库为 100,此时线程 B 把数据库和缓存中的数据都更新成了 200,然后线程 A 又把缓存更新为 100,这样数据库中的值 200 和缓存中的值 100 就不一致了。

  • 直接查询主库

使用前要明确查询的数据量不大,不然会出现主库写请求锁行,影响读请求的执行,最终对主库造成比较大的压力。

3. 实现主库和从库的数据库访问

提前把所有数据源配置在工程中,每个数据源对应一个主库或者从库,然后改造代码,在代码逻辑中进行判断,将 SQL 语句发送给某一个指定的数据源来处理。这个方案简单易实现,但 SQL 路由规则侵入代码逻辑,在复杂的工程中不利于代码的维护。

另一个做法是:独立部署的代理中间件,如 MyCat,这一类中间件部署在独立的服务器上,一般使用标准的 MySQL 通信协议,可以代理多个数据库。该方案的优点是隔离底层数据库与上层应用的访问复杂度,比较适合有独立运维团队的公司选型;缺陷是所有的 SQL 语句都要跨两次网络传输,有一定的性能损耗,再就是运维中间件是一个专业且复杂的工作,需要一定的技术沉淀。

相关推荐

  1. mysql分离

    2024-07-10 21:04:05       40 阅读
  2. MySQL实现分离

    2024-07-10 21:04:05       27 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 21:04:05       5 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 21:04:05       5 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 21:04:05       4 阅读
  4. Python语言-面向对象

    2024-07-10 21:04:05       7 阅读

热门阅读

  1. 纤程和协程理解

    2024-07-10 21:04:05       8 阅读
  2. 几款常见的数字孪生引擎

    2024-07-10 21:04:05       8 阅读
  3. C++:cv.absdiff函数含义

    2024-07-10 21:04:05       11 阅读
  4. 自动回复机器人:源码搭建与智能化客户服务

    2024-07-10 21:04:05       11 阅读
  5. 社群管理新助手:导航群机器人的智能化功能

    2024-07-10 21:04:05       9 阅读
  6. STAR 命令参数解释

    2024-07-10 21:04:05       11 阅读
  7. hid-ft260驱动学习笔记 4 - ft260_uart_ops

    2024-07-10 21:04:05       9 阅读
  8. Git详解

    Git详解

    2024-07-10 21:04:05      9 阅读