MySQL高可用之读写分离笔记

读写分离

读写分离是什么?什么场景下需要读写分离?

MySQL 提供了那些复制模式?分别对应那些应用场景?

怎么避免主从复制延迟?

怎么进行读写分离?

案例背景

假设你目前在某电商平台就职,公司面临双 11 大促,投入了大量营销费用用于平台推广,这带来了巨大的流量,如果你是订单系统的技术负责人,要怎么应对突如其来的读写流量呢?

这是一个很典型的应用场景,我想很多研发同学会回答:通过 Redis 作为 MySQL 的缓存,然后当用户查看“订单中心”时,通过查询订单缓存,帮助 MySQL 抗住大部分的查询请求。

如果你也是这么想,说明没认真思考过问题。因为应用缓存的原则之一是保证缓存命中率足够高,不然很多请求会穿透缓存,最终打到数据库上。然而在“订单中心”这样的场景中,每个用户的订单都不同,除非全量缓存数据库订单信息(又会带来架构的复杂度),不然缓存的命中率依旧很低。

所以在这种场景下,缓存只能作为数据库的前置保护机制,但是还会有很多流量打到数据库上,并且随着用户订单不断增多,请求到 MySQL 上的读写流量会越来越多,当单台 MySQL 支撑不了大量的并发请求时,该怎么办?

案例分析

互联网大部分系统的访问流量是读多写少,读写请求量的差距可能达到几个数量级,就好比你在京东上的商品的浏览量肯定远大于你的下单量。

所以你要考虑优化数据库来抗住高查询请求,首先要做的就是区分读 写流量区,这样才方便针对读流量做单独扩展,这个过程就是流量的“读写分离”

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

MySQL 主从结构

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

案例解决

binlog 实现主从复制的流程

MySQL 的主从复制依赖于 binlog,也就是记录 MySQL 上的所有变化并以二进制形式保存在磁盘中。复制的过程就是将 binlog 中的数据从主库传输到从库上。

这过程一般是异步的,也就是主库执行事务操作的线程不会等待复制 binlog 的线程同步完成。

MySQL 集群的主从复制过程梳理为 3 个阶段:

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

具体详细步骤:

一主 2 从一备

从库的数量是不是越多越好?

不是的。

因为从库的数量增加,从库连接上来的 IO 线程也会增多主库也要创建同样多的 log dump 线程来处理复制请求,主库资源消耗比较高,同事还受限于主库的网络带宽。

主从复制模型

MySQL 主从复制模型有哪些?

  • 同步复制:性能差,需要等待从库复制成功响应,才返回客户端结果。
  • 异步复制(默认模型):MySQL 主库提交事务的线程不会的等待 Binlog 同步完成,就会返回结果。一旦主库宕机,数据就会丢失。
  • 半同步复制: 事务不用等所有的从库复制成功响应,只要一部分成功响应就行。兼顾了上面两种的优点。

从架构上解决主从复制延迟问题

实际案例

我们来结合实际案例设计一个主从复制延迟的解决方案。

在电商平台,每次用户发布商品评论时,都会先调用评论审核,目的是对用户发布的商品评论进行如言论监控、图片鉴黄等操作。

评论在更新完主库后,商品发布模块会异步调用审核模块,并把评论 ID 传递给审核模块,然后再由评论审核模块用评论 ID 查询从库中获取到完整的评论信息。此时如果主从数据库存在延迟,在从库中就会获取不到评论信息,整个流程就会出现异常。

主从延迟影响评论读取的实时性

解决方案

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

  • 使用缓存
  1. 可以在写入数据主库的同时,把评论数据写到 Redis 缓存里,这样其他线程再获取评论信息时会优先查询缓存,也可以保证数据的一致性。
  2. 不过这种方式又会带来缓存和数据库的一致性问题。
  • 直接查询主库
  1. 该方案在使用时一定要谨慎,你要提前明确查询的数据量不大,不然会出现主库写请求锁行,影响读请求的执行,最终对主库造成比较大的压力。

拓展-实现主库和从库的数据访问

  1. 提前把所有数据源配置在工程中,每个数据源对应一个主库或者从库,然后改造代码,在代码逻辑中进行判断,将 SQL 语句发送给某一个指定的数据源来处理。
  2. 另一个做法是:独立部署的代理中间件,如 MyCat,这一类中间件部署在独立的服务器上,一般使用标准的 MySQL 通信协议,可以代理多个数据库。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值