MySQL主从延迟、读写分离的解决方法总结

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于主从延迟和读写分离的解决方法,下面一起来看一下总结了几个方法,希望对大家有帮助。 推荐学习:mysql视频教程 我

    本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于主从延迟和读写分离的解决方法,下面一起来看一下总结了几个方法,希望对大家有帮助。<p><img src="https://img.mryunwei.com/uploads/2023/04/20230417005859537.jpg"></p>

我们都知道互联网数据有个特性,大部分场景都是 读多写少,比如:微博、微信、淘宝电商,按照 二八原则,读流量占比甚至能达到 90%

结合这个特性,我们对底层的数据库架构也会做相应调整。采用 读写分离

处理过程:

客户端会集成 SDK,每次执行 SQL 时,会判断是 写 或 读 操作

如果是 写 SQL,请求会发到 主库

主数据库执行SQL,事务提交后,会生成 binlog ,并同步给 从库

从库 通过 SQL 线程回放 binlog ,并在从库表中生成相应数据

如果是 读 SQL,请求会通过 负载均衡 策略,挑选一个 从库 处理用户请求

看似非常合理,细想却不是那么回事

主库 与 从库 是采用异步复制数据,如果这两者之间数据还没有同步怎么办?

主库刚写完数据,从库还没来得及拉取最新数据,读 请求就来了,给用户的感觉,数据丢了???

针对这个问题,今天,我们就来探讨下有什么解决方案?

一、强制走主库

针对不用的业务诉求,区别性对待

场景一:

如果是对数据的 实时性 要求不是很高,比如:大V有千万粉丝,发布一条微博,粉丝晚几秒钟收到这条信息,并不会有特别大的影响。这时,可以走 从库。

场景二:

如果对数据的 实时性 要求非常高,比如金融类业务。我们可以在客户端代码标记下,让查询强制走主库。

二、从库延迟查询

由于主从库之间数据同步需要一定的时间间隔,那么有一种策略是延迟从从库查询数据。

比如:

因为是采用一刀切,当面对高并发业务场景时,性能会下降的非常厉害,一般不推荐这个方案。

三、判断主从是否延迟?决定选主库还是从库

方案一:

在从库 执行 命令 show slave status

查看 seconds_behind_master 的值,单位为秒,如果为 0,表示主备库之间无延迟

方案二:

比较主从库的文件点位

还是执行 show slave status,响应结果里有截个关键参数

Master_Log_File 读到的主库最新文件

Read_Master_Log_Pos 读到的主库最新文件的坐标位置

Relay_Master_Log_File 从库执行到的最新文件

Exec_Master_Log_Pos 从库执行到的最新文件的坐标位置

两两比较,上面的参数是否相等

方案三:

比较 GTID 集合

Auto_Position=1 主从之间使用 GTID 协议

Retrieved_Gtid_Set 从库收到的所有binlog日志的 GTID 集合

Executed_Gtid_Set 从库已经执行完成的 GTID 集合

比较 Retrieved_Gtid_Set 和 Executed_Gtid_Set 的值是否相等

在执行业务SQL操作时,先判断从库是否已经同步最新数据。从而决定是操作主库,还是操作从库。

缺点:

无论采用上面哪一种方案,如果主库的写操作频繁不断,那么从库的值永远跟不上主库的值,那么读流量永远是打在了主库上。

针对这个问题,有什么解决方案?

这个问题跟 MQ消息队列 既要求高吞吐量又要保证顺序是一样的,从全局来看确实无解,但是缩小范围就容易多了,我们可以保证一个分区内的消息有序。

回到 主从库 之间的数据同步问题,从库查询哪条记录,我们只要保证之前对应的写binglog已经同步完数据即可,可以不用管主从库的所有的事务binlog 是否同步。

问题是不是一下简单多了

四、从库节点判断主库位点

在从库执行下面命令,返回是一个正整数 M,表示从库从参数节点开始执行了多少个事务

timeout 可选, 表示这个函数最多等待 N 秒

缺点:

master_pos_wait 返回结果无法与具体操作的数据行做关联,所以每次接收读请求时,从库还是无法确认是否已经同步数据,方案实用性不高。

五、比较 GTID

执行下面查询命令

阻塞等待,直到从库执行的事务中包含 gtid_set,返回 0

超时,返回 1