• MySQL读写分离


    1、背景

            数据库还是单机部署,依据一些云厂商的 Benchmark 的结果,在 4 核 8G 的机器上运 MySQL 5.7 时,大概可以支撑 500 的 TPS 和 10000 的 QPS。这时,运营负责人说正在准备双十一活动,并且公司层面会继续投入资金在全渠道进行推广,这无疑会引发查询量骤然增加的问题。当查询请求增加时,我们应该如何做来解决问题?答案是主从读写分离。

    2、主从读写分离

            大部分系统的访问模型是读多写少,读写请求量的差距可能达到几个数量级。比如购物网站上一个商品的浏览量也肯定远大于它的下单量。

            数据库如何抗住更高的查询请求,那么首先你需要把读写流量区分开,因为这样才方便针对读流量做单独的扩展。它其实是个流量分离的问题,就好比道路交通管制一样,一个四车道的大马路划出三个车道给领导外宾通过,另外一个车道给我们使用,优先保证领导先行,就是这个道理。这个方法本身是一种常规的做法,即使在一个大的项目中,它也是一个应对数据库突发读流量的有效方法。

            流量突增导致从库负载过高的问题,可以优先做几个从库扩容上去,这样对数据库的读流量就会落入到多个从库上,其他的从库的负载就降了下来。

    3、主从读写的关键点

            主从读写分离有两个技术上的关键点:

    • 主从复制:主库数据拷贝到从库;
    • 扩展:在主从分离的情况下,我们如何屏蔽主从分离带来的访问数据库方式的变化,让开发同学像是在使用单一数据库一样。

    3.1 主从复制的过程

            首先从库在连接到主节点时会创建一个 IO 线程,把接收到的 binlog 信息写入一个叫做 relay log 的日志文件中,而主库也会创建一个 log dump 线程来发送 binlog 给从库;同时,从库还会创建一个 SQL 线程读取 relay log 中的内容,并且在从库中做回放,最终实现主从的一致性。

    这里面涉及到三个线程:

    • IO线程:连接到 master 获取 binlog,并且解析 binlog 写入中继日志,这个线程叫做 I/O 线程。
    • log dump线程:master 节点上有一个 log dump 线程,是用来发送 binlog 给 slave 的。
    • sql线程:从库的 sql 线程,是用来读取 relay log,把数据写入到数据库的。 

    3.2 主从复制三种同步方式

    • 全同步复制(Fully synchronous replication)
      • 指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。
      • 问题:因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
    • 异步复制(Asynchronous replication)
      • MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给客户端,并不关心从库是否已经接收并处理。
      • 问题:主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
    • 半同步复制(Semisynchronous replication)
      • 介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。
      • 问题:相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

            基于性能的考虑,可以选择异步复制。数据不一致这种情况出现的概率很低,对于互联网的项目来说是可以容忍的。

    3.3 从库数量

            是不是我无限制地增加从库的数量就可以抵抗大量的并发呢?

            实际上并不是的。因为随着从库数量增加,从库连接上来的 IO 线程比较多,主库也需要创建同样多的log dump 线程来处理复制的请求,对于主库资源消耗比较高,同时受限于主库的网络带宽,所以在实际使用中,一般一个主库最多挂 3~5 个从库。

            阿里云的集群从节点最多4个:集群版RDS实例的优势及应用场景_云数据库 RDS-阿里云帮助中心

    4、主从延迟

    4.1 问题

            在发微博的过程中会有些同步的操作,像是更新数据库的操作,也有一些异步的操作,比如说将微博的信息同步给审核系统,所以我们在更新完主库之后,会将微博的 ID 写入消息队列,再由队列处理机依据 ID 在从库中获取微博信息再发送给审核系统。此时如果主从数据库存在延迟,会导致在从库中获取不到微博信息,整个流程会出现异常。

    4.2 解决方案

            解决核心思想就是尽量不去从库中查询信息。

    数据的冗余-推荐

            发送消息队列时不仅仅发送微博 ID,而是发送队列处理机需要的所有微博信息,借此避免从数据库中重新查询数据。

    使用缓存

            在同步写数据库的同时,也把微博的数据写入到redis缓存里面,这样队列处理机在获取微博信息的时候会优先查询缓存,这样也可以保证数据的一致性。

    查询主库

           在队列处理机中不查询从库而改为查询主库。不过,这种方式使用起来要慎重,要明确查询的量级不会很大,是在主库的可承受范围之内,否则会对主库造成比较大的压力。

    总结

            下面都是以问题为例提供解决方案,具体业务需要具体分析。方案推荐使用数据的冗余。

    5、读写分离工具

    参考文章:

    MySQL实现主从复制的原理详解_Mysql_脚本之家

  • 相关阅读:
    访问学者在国外需要特别注意的安全问题
    LabVIEW代码生成错误 61056
    MongoDB环境搭建
    皕杰报表中填报控件显示模式控制问题
    优思学院|简单而强大的5W1H提问法
    【yolov8目标检测】使用yolov8训练自己的数据集
    MIUI13 USB调试Android应用失败INSTALL_FAILED_USER_RESTRICTED
    JD-怎样获取别人家店铺商品的API接口呢??
    2022绵阳+dp经典问题
    Navicat15工具连接PostgreSQL15失败
  • 原文地址:https://blog.csdn.net/xixingzhe2/article/details/133748424