线上问题——学习记录幂等判断失效问题分析

一、业务流程

image.png
上图是对save和saveScore两个接口的流程抽象,save是上传答题数据,saveScore则是上传答题分数,为保证幂等和防止并发调用,这两个接口都加了分布式锁(还是两层哦)。第一层使用的是不同的锁,因为处理的是不同的表,第二层处理的是相同的表,为了保证数据在某个维度上的唯一,所以使用了相同的锁。本篇文章则主要记录下表C中的逻辑唯一键出现重复数据的问题排查过程,该问题包含了对锁、事务及Mybatis框架的综合运用和理解。

二、问题分析

ROUND 1

问题分析

最开始只看到了第二层锁的逻辑,始终无法想通,两个接口获取的同一把锁,且加锁后都做了幂等判断,查询缓存和数据库,没有再插入,有则更新,C表的重复数据是怎么来的呢?从链路上分析,save先获取到第二层锁,插入了数据;释放锁后,saveScore开始执行,这时候查询数据库返回的结果居然是null!
这时候首先想到的是save的事务没有提交,但查看代码,事务是在获取锁3后才开启的,因此save释放锁3前,事务必定也是提交了的,而saveScore也是在获取锁3后才开启的事务。
image.png
image.png
我想大部分同学到这里会定义为玄学问题,但作为一个资深码农,要相信一切问题必有根因(除非真的是玄学)。最终,终于在saveScore的入口找到了罪魁祸首。
image.png
问题很简单,在锁3的调用入口处已经开启了事务,当save执行第二层逻辑提交事务之前,saveScore已经开启了事务,由于事务的隔离性(可重复读),在获取到锁3时,查询的是事务开始时的快照,即使save的事务已经提交,对于saveScore来说也是不可见的。

解决方案

这里修改方法目前想到以下几种:

  • 让save和saveScore串行化,但这两个接口是主链路上的核心接口,并发量很高,这样会导致性能降低,除非必要不会考虑。
  • 去掉saveScore第一层逻辑的事务,但这样无法保证这几个表的一致性。
  • 将saveScore第二层逻辑也改为异步,那每次调用时都会新启一个事务,同时还能提高接口的并发度,但是这要取决于业务,改动影响较大。
  • 设置saveScore的第二层事务传播级别为REQUIRED_NEW,这样也是每次会开启一个新的事务,也就能读取到save提交的数据了。

综合考虑,设置传播级别是影响最小的(有其它想法的欢迎补充),如果业务方能接受saveScore异步处理,那么这种方法则是最优的。
问题分析到这就结束了?当然没有。

ROUND 2

从流程图上可以看到,表C、D、E是在一个事务里的,那为什么只有表C有重复,表D、E数据却是正常的呢?
先说表E,这个比较简单,首先该表有唯一索引,不像前两个表只有普通索引,其次,业务上该表存放的数据粒度更粗,也就是前面两个表多次插入,这个表只会插入一次,其余都是更新,所以就算没有唯一索引,出现重复记录的概率也远比前两个表小很多。
再看表D,这个表可真的是让我一度以为是自己对事务理解没到位,经过反复验证,证明自己理解是没有问题的。那真的是玄学?于是请教了大佬。
经过大佬分析,事实证明我想的太简单了,最后得到一个推翻上面所有分析的结论。首先我们数据库事务隔离级别设置的read committed,不是repeatable read(是我太想当然,先入为主了)。那么表D、E没有重复数据就能解释了(事实上表D还是有重复数据存在,只是不是当前分析的链路,不过那又是另外一个问题,稍后分析);但是为啥表C的幂等判断失效了呢?
image.png
对表C采用的是双重校验,从链路上看两次查询C都是没有查到数据的,所以才会新增一条,但能获取到锁3说明另一个事务已经提交,当前事务由于是read committed一定也能查询到数据才对,那说明只有一种可能,锁内的查询C是从缓存查的,不是从数据库查的l。
image.png
从阿里云的sql洞察上也能验证这个猜想,按照代码逻辑,saveScore应该有两次查询才对,但实际上只有一条,说明有一次查询(结合skywalking分析得到是第二次没有查数据库)没有到达数据库。我们这个链路上的表都是做了redis缓存的,但是如果是第一次查询是null值,根本不会缓存到redis,那还有什么缓存会拦截到查询SQL呢?还有一个我们平时可能都忽略了的,那就是Mybatis的一二级缓存,一级缓存是默认开启的。先来复习一下Mybatis的一级缓存:
image.png
我们这里的两次查询是完全一样的,且是在同一个sqlSesson极短时间内重复查询,中间没有更新,完全符合一级缓存的使用条件,就是这玩意儿搞得鬼,我以前也没遇到过这个问题,所以也忽略了Mybatis的这个机制,还一直认为这玩意儿就是个摆设,这次算是给我上了一课。

ROUND 3

最后再回头来看看为啥D表也有重复的数据,下图是统计的部分重复数据:
image.png
这个其实很简单,上文细心的朋友可以发现我的分析都是按照save先执行,saveScore后执行的逻辑来分析的,但这两个接口执行时序其实不是固定的,当saveScore先执行,再获取到锁二时就已经开启了事务,即使锁3释放了,内层事务2也不会提交,因为和外层事务是同一个事务,那么save获取到锁3开始执行时也查不到数据,就会重复插入了。这里要解决的话也可以把内层事务传播级别声明为REQUIRED_NEW即可,对业务也没有影响。

三、总结

这次的问题好在对业务没有什么影响,但代码确实写的有问题,考验了对锁、事务以及框架的总和运用和理解。另外在分析问题时不要想当然,先入为主,一定要大胆猜想、亲手验证,只要有发现一点疑点就不应该发放过,因为很有可能就这一个疑点就推翻之前所有的分析。
最后附上链路:F947DF6DC8C94E339ED1BAC5AF5E9812(edu-study、edu-study-async),感兴趣的看官可自行分析验证,有问题欢迎指出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/721577.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【笔记】Android 漫游定制SPN定制有关字段

一、SPN模块简介 【笔记】SPN和PLMN 运营商网络名称显示 Android U 配置 WiFiCalling 场景下PLMN/SPN 显示的代码逻辑介绍 【笔记】Android Telephony 漫游SPN显示定制(Roaming Alpha Tag) 二、相关配置字段 non_roaming_operator_string_array 是否…

共筑前端学习之路:欢迎加入我们的前端组件学习交流群

共筑前端学习之路:欢迎加入我们的前端组件学习交流群 随着信息技术的飞速发展,前端开发作为构建数字化世界的重要一环,越来越受到广大开发者的关注和重视。为了更好地服务于前端开发者,尤其是那些对前端组件充满热情的粉丝&#x…

【Leetcode每日一题】 前缀和 - 除自身以外数组的乘积(难度⭐⭐)(26)

1. 题目解析 题目链接:238. 除自身以外数组的乘积 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 核心在于计算题目所给数组除本身外其他元素的积的数组返回即可。 2. 算法原理 为了计算每个位置i的最终结果ret[i]&…

基于java springboot+redis网上水果超市商城设计和实现以及文档

基于java springbootredis网上水果超市商城设计和实现以及文档 博主介绍:多年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留…

Day17:信息打点-APP资产知识产权应用监控静态提取动态抓包动态调试

目录 案例1:名称获取APP信息(爱企查/小蓝本/七麦/点点) 案例2:URL网站备案查APP 案例3:APP提取信息-静态分析 案例3:APP提取信息-动态抓包 案例4:APP提取信息-动态调试 思维导图 章节知识…

Centos8 yum方式安装Redis

Centos8 yum方式安装多个Redis 是否安装GCC依赖 ggc -v #或者 rpm -q gcc安装GCC yum install -y gcc如果不是管理员 加 sudo sudo yum install -y gcc yum安装Redis yum install redis失败更新yum 再安装 #添加EPEL仓库 sudo yum install epel-release#更新yum源 sudo yum upd…

智能电网监控:图像分类技术在能源电力领域的创新应用

一、引言 在当今这个对能源效率要求日益增长的时代,电力行业正面临着前所未有的挑战。为了满足日益增长的电力需求,同时确保电网的稳定性和可靠性,我们采用了一种革命性的方法:通过智能算法和自动化技术来优化电网的运行。这一项…

网络学习:SMart link技术与Monitor link技术

目录 一、SMart link技术 1.1、SMart link技术简介 1.2、SMart link技术原理及基础知识点 1、应用场景(举例): 2、运行机制 3、保护vlan 4、控制VLAN 5、Flush报文 6、SMart link的负载分担机制 7、SMart link角色抢占模式 二、Mo…

中文文本分类_1(pytorch 实现)

import torch import torch.nn as nn import torchvision from torchvision import transforms, datasets import os, PIL, pathlib, warningswarnings.filterwarnings("ignore") # 忽略警告信息# win10系统 device torch.device("cuda" if torch.cuda.i…

三级分销数据库设计

一,数据结构 二,查询方法 1.mysql递归查询 获取id9的所有上级 r : 9 设置自己所要搜索子节点的id SELECTT2.* FROM(SELECTr AS _id,( SELECT r : pid FROM sj_user WHERE id _id ) AS 2v2,l : l 1 AS lvl FROM( SELECT r : 9 ) vars, -- 查询id为…

软考信息系统项目管理师零基础怎么学习?

软考考信息系统项目管理师,零基础怎么入手高项? 要我说对于没有基础的人群来说零基础考信息系统项目管理师还是有一定的难度的,难就难在需要时间去了解基础,而相对于系统分析师、系统构架设计师、网络规划设计师、系统规划与管理…

软考59-上午题-【数据库】-小结+杂题

一、杂题 真题1: 真题2: 真题3: 真题4: 真题5: 真题6: 真题7: 真题8: 二、数据库总结 考试题型: 1、选择题(6题,6分) 2、综合分析题…

3分钟开通GPT-4

AI从前年12月份到现在已经伴随我们一年多了,还有很多小伙伴不会开通,其实开通很简单,环境需要自己搞定,升级的话就需要一张visa卡,办理visa卡就可以直接升级chatgptPLSU 一、虚拟卡支付 这种方式的优点是操作简单&…

使用java的Stream流进行Collectors.groupingBy分组后生成Map,对Map进行删除原集合是否会发生改变

在Java中,当我们使用Collectors.groupingBy方法对集合进行分组操作时,生成的新映射(Map)是基于原始集合(allItems)的数据结构和内容创建的。这意味着,如果你更改了新的映射allItemMap中的值&…

web游戏-飞机大战

H5小游戏源码、JS开发网页小游戏开源源码大合集。无需运行环境,解压后浏览器直接打开。有需要的,私信本人,发演示地址,可以后再订阅,发源码,含60+小游戏源码。如五子棋、象棋、植物大战僵尸、开心消消乐、扑鱼达人、飞机大战等等 <!DOCTYPE html> <html lang=&q…

ardupilot 及PX4姿态误差计算算法对比分析

目录 文章目录 目录摘要1.APM姿态误差计算算法2.PX4姿态误差计算算法3.结论摘要 本节主要记录ardupilot 及PX4姿态误差计算算法差异对比过程,欢迎批评指正。 备注: 1.创作不易,有问题急时反馈 2.需要理解四元物理含义、叉乘及点乘含义、方向余弦矩阵含义、四元数乘法物理含…

2024年2核4G服务器优惠价格,选阿里云还是腾讯云?

2核4G云服务器选阿里云还是腾讯云&#xff1f;2核4G服务器多少钱一年&#xff1f;1个月费用价格&#xff1f;腾讯云轻量2核4G5M带宽服务器165元一年、252元15个月、三年756元&#xff0c;阿里云2核4G4M带宽轻量服务器165元12个月、ECS云服务器2核4G配置30元3个月、2核4G5M带宽1…

MySQL 多表查询 连接查询 自连接

介绍 自连接查询&#xff0c;可以是内连接查询&#xff0c;也可以是外连接查询&#xff0c;一句话自己连接自己&#xff0c;一个表当作两个表进行连接。 语法 SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件两个表A说明是同一张表&#xff0c;但是别名不同 案例…

文献速递:深度学习疾病预后--使用深度学习对数字病理图像进行胃癌的准确诊断和预后预测:一项回顾性多中心研究

Title 题目 Accurate diagnosis and prognosis prediction of gastric cancer using deep learning on digital pathological images: A retrospective multicentre study 使用深度学习对数字病理图像进行胃癌的准确诊断和预后预测&#xff1a;一项回顾性多中心研究 01 文献…

OpenMMlab AI实战营第四期培训

OpenMMlab AI实战营第四期培训 OpenMMlab实战营第四次课2023.2.6学习参考一、什么是目标检测1.目标检测下游视觉任务2.图像分类 v.s. 目标检测 二、目标检测实现1.滑窗 Sliding Window2.滑窗的效率问题3.改进思路&#xff08;1&#xff09;消除滑窗中的重复计算&#xff08;2&a…