踩坑MySQL主从延迟背景下,流程业务卡住无法流转,问题得以暴露。
背景
今天这个问题我们的监控没有提前观测到,属于业务处理时未考虑到主从同步,用户反馈过来时,距离问题发生其实已经过去了几天。
我们有个业务流程表:t_apply
,基本流程:
- 我们的服务端应用
biz-server
接收到用户提交的数据,创建一条申请单数据。 - 触发外部依赖的一个校验服务
validation-server
,这个校验动作一般耗时:10ms-10s。 - 校验服务处理完成后回调
biz-server
接口,更新我们的申请单状态。
很清晰、简单的一个流程。
其中1-2隐含了MySQL
主从复制的过程。
而今天爆出的业务问题时:数据提交了,申请单状态却卡在了INIT
状态,也就是校验状态未成功回写。
正常的状态变化:INIT
->NODE1
。同时,我们的业务MySQL
一个实例被多个业务方共享。
问题排查
查日志
出现问题先查日志: 发现回调是有触发的,而回调内的更新状态的sql却没有执行(对应日志没打出来)。
疑问
什么情况会导致select
出的数据是空的呢?正好我们前两天刚好解决过一个主从同步延迟导致的问题,所以经验告诉我:发生了主从同步延迟。
验证
查问题还是应该有依据才能得出可靠的结论。对照了两个时间点:
- 数据创建的时间点:Thu Dec 16 2021 18:47:25 GMT+0800 (China Standard Time)
- 校验服务回调的时间点:Dec 16, 2021 @ 18:47:33.387
耗时秒级别,属于前期接入此校验服务时正常预期范围。
观察数据库监控大盘:
对比16号的TPS与最近一周的TPS数据,发现平时TPS大约为500,而16号达到了差不多7k的量。到这里已经可以看到12.16下午六点多开始出现数据库流量尖刺。
如上通过数据库的监控大盘,我们找到了问题(主从复制延迟)以及问题原因(DML
尖刺带来TPS
激增)。
综上,我们画出问题对应时序图: 时序图帮助我们更形象地表达问题过程。
问题解决
到此我们定位到了问题:主从复制延迟。
以及分析出了问题原因:DML
尖刺带来TPS
激增。
同时为了更好地解决问题,我拜托了DBA大佬帮忙导出了16号18点到19点的DML
语句(解析binlog
行),这一步可以帮助我们分析是否为其他公用MySQL
资源的业务方带来的DML
流量尖刺。
资源充足
经分析对应时段DML
语句,我们发现有很多数据写入是其他业务带来的,如果资源充足,我们可以隔离多个业务间的DB
资源。
资源不太充足 | 业务要求不高
DB
资源没那么充足或者业务要求并没那么高(这里主要指MySQL
主从复制的延迟容忍度)的情况下,比如今天排查的这个应用属于集团toB
业务,资源要求不高,那么我们不单独申请DB
资源。
在这个框架内,我们依然可以改善、解决问题:
callback
业务方法或者对应select
语句处,强制指定主节点数据源:@DS("master")
callback
业务方法处:指定事务:@Transactional(rollbackFor = Throwable.class)
,使用的mybatis-plus
主从切换如果在事务内默认读主节点数据
同时排除带来DML
尖刺的业务操作(超出了当前数据库处理的能力)。
数据库优化
主库的TPS
并发越高,产生的DML
数量就越超过slave
单线程的处理能力,延迟也就越大。新版本MySQL
主从复制已支持多线程,因此升级MySQL
是一个优化点。如果此时slave
查询锁等待过多,也会影响复制进度。
反思
纵观整个过程,你会发现,这又是一例因为错误实现导致的问题。所以:
- 提高团队的战斗力志在必行。
- 问题解决后带来的是宝贵的经验,珍惜问题,把每个问题解决好。
- 实现一个方法的时候,最好同时能有整体架构的高度思考。