MySQL篇:MySQL主从集群同步延迟问题

MySQL主从集群同步延迟问题

😄生命不息,写作不止

🔥 继续踏上学习之路,学之分享笔记

👊 总有一天我也能像各位大佬一样

🏆 博客首页 @怒放吧德德 To记录领地 @一个有梦有戏的人

🌝分享学习心得,欢迎指正,大家一起学习成长!

转发请携带作者信息 @怒放吧德德(掘金) @一个有梦有戏的人(CSDN)

问题

在使用 MySQL 集群的时候,我们都是采用了主从架构,主用来负责读,从用来负责写,但是这可能会存在从库去主库同步数据的时候会发生延迟问题。

原因

发生主从集群同步延迟问题有许多的原因,可以通过之前的一篇文章《BufferPool缓存机制》介绍了具体的 MySQL 执行流程。首先,我们需要简单了解一下主从同步机制。

主从同步机制

如图所示来简单介绍主从同步机制,核心组件是:主数据库负责写数据,并且记录到 binlog 中;从数据库接收主数据库的二进制日志,重放日志以同步数据。

同步流程:

  1. 二进制日志记录 \ 主库将所有数据变更(如INSERT、UPDATE、DELETE)以事件形式写入二进制日志(binlog)。
  2. 从库I/O线程
    • 从库通过I/O线程连接主库,请求二进制日志。
    • 主库的Binlog Dump线程将日志事件发送给从库。
    • 从库将接收的日志事件写入本地中继日志(Relay Log)
  3. 从库SQL线程
    • 从库的SQL线程读取中继日志中的事件,并按顺序执行,更新从库数据。
    • 执行完成后,中继日志会被清理。

注:既然是百科,只是简单了解,对于主从同步机制,后续会详细写一篇文章记录在 MySQL 专栏。

在这个同步数据的过程中都是异步实现的,那么主节点是不会关心从节点是否同步成功。然而导致延迟的可能原因就如下

网络延迟

主从之间的数据同步是通过网络传输,在网络传输比较慢或者存在网络延迟就会出现子节点同步的数据发生延迟。主从跨机房或网络带宽不足,导致binlog传输延迟。

资源压力

无论是主节点还是从节点的压力过大,导致资源不满足压力的需求,也会导致主从延迟。从库处理SQL线程时资源耗尽,无法及时应用事务。从库的relay log写入或数据文件更新速度慢(如机械硬盘 vs SSD)。

大事务与长事务

当主库存在大批量更新或者长时间未提交事务,导致从库必须串行重放该事务,阻塞后续事件。如果代码中有慢 SQL ,也会导致主从同步延迟。

解决方案

诊断

  • 可以在从库通过 Show Replica Status查看同步状态,还可以通过 Seconds_Behind_Master查看延迟时间(单位秒,数值越大表示延迟越严重)。
  • Slave_IO_Running/Slave_SQL_Running查看从库线程是否正常。
  • 网络:使用 ping、traceroute 或 iftop 检查主从间网络延迟和带宽。
  • 磁盘:通过 iostat -dx 1 或 iotop 查看磁盘负载,特别是主库的binlog和从库的relay log所在磁盘。
  • 事务:主库查询 information_schema.innodb_trx 查看未提交事务,分析binlog(mysqlbinlog)确认事务大小。

解决

  1. 网络优化:检查优化主从之间的网络环境,主从库部署在同机房或通过专线连接,减少网络延迟。使用专线或压缩传输(slave_compressed_protocol=ON)。
  2. 资源压力:如果主从数据库的资源存在压力,可以增加资源、减低请求量、垂直拆分大表,水平分片分散写入压力。主从使用SSD,确保磁盘I/O吞吐量。
  3. 大事务与长事务:如果有大事务,可以进行拆分大事务,将单次操作拆分为小批次。还要避免长时间锁表,也可以设置事务超时。
  4. 参数配置:
    • sync_binlog 设置为 1000(或更高),减少每次事务提交时刷盘次数,但需权衡数据安全性。
    • innodb_flush_log_at_trx_commit 将其设置为 2 或 0 ,控制事务日志的刷新频率,可以减少延迟。
    • slave_parallel_workers 设置为从库CPU核心数的倍数(如4-8),启用多线程复制。
    • slave_parallel_type设置为 LOGICAL_CLOCK(MySQL 5.7+),基于事务组并行执行,提升效率。
    • 启用 gtid_modeenforce-gtid-consistency,将其设置 ON,GTID(全局事务标识符)复制方式能够简化主从复制,可以减少复制冲突,避免某些类型的同步延迟。
    • 主库设置 rpl_semi_sync_master_enabled=1,从库设置 rpl_semi_sync_slave_enabled=1,确保至少一个从库接收日志后再提交事务(MySQL 5.7+建议使用 AFTER_SYNC 模式)来启用半同步复制。

备注

对于两个重要配置说明,以下引用博客网[孟凡柱的专栏]的一段内容

sync_binlog 配置说明:

sync_binlog:这个参数是对于MySQL系统来说是至关重要的,他不仅影响到Binlog对MySQL所带来的性能损耗,而且还影响到MySQL中数据的完整性。对于"sync_binlog"参数的各种设置的说明如下:

sync_binlog=0,当事务提交之后,MySQL不做fsync之类的磁盘同步指令刷新binlog_cache中的信息到磁盘,而让Filesystem自行决定什么时候来做同步,或者cache满了之后才同步到磁盘。

sync_binlog=n,当每进行n次事务提交之后,MySQL将进行一次fsync之类的磁盘同步指令来将binlog_cache中的数据强制写入磁盘。

在MySQL中系统默认的设置是sync_binlog=0,也就是不做任何强制性的磁盘刷新指令,这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。而当设置为"1"的时候,是最安全但是性能损耗最大的设置。因为当设置为1的时候,即使系统Crash,也最多丢失binlog_cache中未完成的一个事务,对实际数据没有任何实质性影响。

从以往经验和相关测试来看,对于高并发事务的系统来说,"sync_binlog"设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多。

innodb_flush_log_at_trx_commit 配置说明

默认值1的意思是每一次事务提交或事务外的指令都需要把日志写入(flush)硬盘,这是很费时的。特别是使用电 池供电缓存(Battery backed up cache)时。设成2对于很多运用,特别是从MyISAM表转过来的是可以的,它的意思是不写入硬盘而是写入系统缓存。日志仍然会每秒flush到硬 盘,所以你一般不会丢失超过1-2秒的更新。设成0会更快一点,但安全方面比较差,即使MySQL挂了也可能会丢失事务的数据。而值2只会在整个操作系统 挂了时才可能丢数据。

学习内容

阿里高频面试之Mysql 主从集群同步延迟问题怎么解决?_哔哩哔哩_bilibili

【大厂面试题】mysql主从同步延迟解决方案_哔哩哔哩_bilibili

深入解析Mysql 主从同步延迟原理及解决方案 - 孟凡柱的专栏 - 博客园


转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人

持续创作很不容易,作者将以尽可能的详细把所学知识分享各位开发者,一起进步一起学习。转载请携带链接,转载到微信公众号请勿选择原创,谢谢!

👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍

谢谢支持!

相关推荐
Asthenia04128 小时前
Spring AOP 和 Aware:在Bean实例化后-调用BeanPostProcessor开始工作!在初始化方法执行之前!
后端
Asthenia04129 小时前
什么是消除直接左递归 - 编译原理解析
后端
Asthenia04129 小时前
什么是自上而下分析 - 编译原理剖析
后端
Asthenia041210 小时前
什么是语法分析 - 编译原理基础
后端
Asthenia041210 小时前
理解词法分析与LEX:编译器的守门人
后端
uhakadotcom10 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
Asthenia041211 小时前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端