因为锁的问题,我们被扣了1万

2023-05-16

前言

春节放假期间,一个项目上的积分接口被刷,而且不止一个人在刷,并且东西也被兑走,放假晚上被人叫起来排查问题,通过这个人的积分明细观察,基本一秒就能获取一次,远远超过了积分规则限定的次数,这肯定是用脚本了,虽然后期联系死活说自己是正常途径获取。由于是业主,我们还是决定自己来承担这个损失,被项目方从合同中扣除奖品费用1万余元。

问题原因

先说下接口的逻辑层次结构:

–controller 积分获取接口,用PointController表示

–service 积分获取接口service,用PointService表示

我用伪代码来表示整个调用逻辑:

PointController

@RestController
public class PointController {

	@Resource
	private PointService pointService;

	@GetMapping(/addPoint)
	public Response addPoint() {
		//分布式锁,使用redis的NX命令
		RedisDistributedLock lock = new RedisDistributedLock();
    //创建一个3s过期,100ms休眠的锁
		if(lock.lock("POINT_KEY", 3000L, 100L)) {
			try {
        //调用
				pointService.addPoint();
			} catch (Exception ex) {
				e.printStackTrace;
			} finally {
        //解锁
				lock.unlock("POINT_KEY");
			}
		}
		return Response.ok(getLastPoint());
	}
}
  1. 创建一个分布式锁对象,该分布式锁使用redis的NX命令实现
  2. 随后创建一个3s过期的分布式锁,以便锁住该新增积分的请求
  3. 最后在新增积分执行完后,在finally中释放锁
  4. 最后返回该用户的最终积分

PointService

public class PointService {
  
  @Transactional(rollbackFor = Exception.class)
  public void addPoint() {
    //查询积分规则
    PointRule pointRule = getPointRule();
    //查询用户该积分项的积分获取记录总数
    Integer total = getPointRecords();
    //判断该用户的积分记录总数是否大于 积分规则限定的次数
    //大于则不处理,返回
    if(total - pointRule.getRuleTimes >= 0) {
      return;
    }
    
    //生成积分记录
    int insert = insertPointRecords();
    //更新用户总积分
    if(insert > 0) {
      updateUserPoint();
    }
  }
}

PointService 中的添加积分逻辑:

  1. 首先查询该项目积分规则,查询用户该积分项的积分获取记录总数
  2. 判断该用户的积分记录总数是否大于 积分规则限定的次数,大于则不处理,返回
  3. 生成积分记录
  4. 更新用户总积分

该添加积分的逻辑整体上看好像没什么问题,也确实在一切正常的情况下运行是不会有问题的。

如果PointService 中的添加积分逻辑在分布式锁有效期3s内执行完,是不会有问题的。

但如果PointService中的添加积分逻辑超过3s…那是不是后续请求又可以获取锁了,这也正是这次事故的原因。

因为PointService中的添加积分逻辑超过了3s,并且上一个请求的事务还未提交,后续请求已经获取锁进入PointService,在查询积分记录后,判断还是满足规则,继续执行后续的逻辑,造成用户能够获取多次积分。

问题处理

原因总结一下:

  1. 添加积分逻辑处理时间过长
  2. 分布式锁超时

第一个问题:逻辑改动过大,需要时间调整,没有采用

第二个问题:换成Redisson,因为redisson在即使超时的情况下也会续锁,避免锁超时

总结

一方面因为忙于做项目,忽略了代码Review,另一方面测试的时候没有对接口进行并发测试,或者根本没有测出来,第三没有监控工具监控长事务,以及频繁请求。

作者其他文章:
《Prometheus+Grafana 实践派》专栏火热更新中

  1. Grafana 的介绍和安装
  2. Grafana监控大屏配置参数介绍(一)
  3. Grafana监控大屏配置参数介绍(二)
  4. Grafana监控大屏可视化图表
  5. Grafana 查询数据和转换数据
  6. Grafana 告警模块介绍
  7. Grafana 告警接入飞书通知

Spring Boot Admin 系列

  1. Spring Boot Admin 参考指南
  2. SpringBoot Admin服务离线、不显示健康信息的问题
  3. Spring Boot Admin2 @EnableAdminServer的加载
  4. Spring Boot Admin2 AdminServerAutoConfiguration详解
  5. Spring Boot Admin2 实例状态监控详解
  6. Spring Boot Admin2 自定义JVM监控通知
  7. Spring Boot Admin2 自定义异常监控
  8. Spring Boot Admin 监控指标接入Grafana可视化
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

因为锁的问题,我们被扣了1万 的相关文章

随机推荐

  • VC++2017关于项目"const char *" 类型的实参与 "char *" 类型的形参不兼容错误的解决方法

    34 const char 34 类型的实参与 34 char 34 类型的形参不兼容 函数形参为char 的类型直接写入字符串报错 解决办法 xff1a 在项目属性 gt C C 43 43 gt 语言中的符合模式项 选择 否
  • 详解VS2017使用scanf报错的解决方法

    1 在程序最前面加 xff1a define CRT SECURE NO DEPRECATE 2 在程序最前面加 xff1a pragma warning disable 4996 3 把scanf改为scanf s xff1b 4 无需在
  • 在MATLAB中手动安装MinGW64详细教程

    在MATLAB中手动安装MinGW64详细教程 话题背景 针对MATLAB官方License限制附件安装的问题 xff0c 可以尝试线下手动自行安装 部分版本的Matlab由于License到期问题或者破解版限制 xff0c 已无法获得Ma
  • ubuntu18.04部署jenkins,图文并茂,记录一下。

    1 因为Jenkins运行需要jdk的环境 xff0c 所以首先得安装Java xff0c 先下载jdk安装包 xff08 听说用wget下载安装时会有问题 xff0c 说是什么Oracle的安装协议 xff0c 本人用wget亲测 xff
  • 通过hdparm将挂载的硬盘休眠再关机

    hdparm Y dev sda1 root 64 cubietruck plus span class token comment hdparm span hdparm get set hard disk parameters versi
  • 教程 | 简单实用的pandas技巧:如何将内存占用降低90%

    pandas 是一个 Python 软件库 xff0c 可用于数据操作和分析 数据科学博客 Dataquest io 发布了一篇关于如何优化 pandas 内存占用的教程 xff1a 仅需进行简单的数据类型转换 xff0c 就能够将一个棒球
  • 哈佛大学cs50课程笔记_哈佛CS50指南:如何为您选择正确的课程(带有免费证书)

    哈佛大学cs50课程笔记 In January I wrote an article on Class Central about CS50 Harvard s Introduction to Computer Science which
  • 使用Docker快速安装部署mysql

    使用Docker快速安装部署mysql的前提 xff1a 首先需要确保已经安装了Docker环境 如果没有安装Docker的话 xff0c 可以参考上一篇的内容 xff1a Linux上安装Docker 有了Docker环境后 xff0c
  • docker下gitlab安装配置使用(完整版)

    docker 安装gitlab以及使用 一 安装及配置 1 gitlab镜像拉取 gitlab ce为稳定版本 xff0c 后面不填写版本则默认pull最新latest版本 docker pull gitlab gitlab ce 拉取镜像
  • Linux 配置Gradle

    一 下载gradle 如果windows中有可以直接拷贝 xff0c 如果没有可以去官网下载 http www gradle org downloads 二 解压下载得到的gradle unzip gradle 2 2 1 all zip
  • gitlab配置通过smtp发送邮件(QQ exmail腾讯企业为例)

    首先祭出官网文档链接 xff1a https docs gitlab com omnibus settings smtp html 其实官网已经说的很清楚了 xff0c 并且给出了QQ邮箱的范例 xff08 BAT还是屌的 xff09 1
  • 文本编辑器Notepad++使用技巧

    除了语法高亮 xff0c 一般不用操作 还有两点经常使用的 xff1a 正则表达式查找替换和列模式编辑 这些可以在VS Eclipse Word等里也有 xff0c 但是有时打开一个文件就慢了 本来想总结记录一下技巧的 xff0c 却无意中
  • linux系统磁盘block、inode占满处理

    1 磁盘的block占满 xff0c 查看命令 df vh 然后查看占用百分比 2 磁盘inode占满 xff0c 查看命令df ih 同样也是查看占用百分比 block占满处理办法 需要用到的命令如下 LL 列出当前目录下的文件 df v
  • Code::Blocks平台下Fortran的编译

    问题背景 xff1a 因为之前学习数值方法 xff0c 有用到Fortran的地方 xff0c 所以上网查了一些资料 关于Fortran语言的编辑器安装 xff0c 目前本人接触到的支持Fortran的编辑器有VisualStdio和Cod
  • powershell远程连接

    在Linux中 xff0c 我们可以使用安全的SSH方便的进行远程管理 但在Windows下 xff0c 除了不安全的Telnet以外 xff0c 从Windows Server 2008开始提供了另外一种命令行原创管理方式 xff0c 那
  • 2022年学习总结暨2023年规划

    2022年总结 2022年是我在C站的创作元年 xff0c 在第一年也收获了不少成就 xff0c 比如 Java领域新星创作者 发布100篇博文 拿到了C站的书包 吃到了C站的月饼 成功上榜了330 43 截止目前收获粉丝8600 43 在
  • 《Prometheus+Grafana 实践派》专栏介绍

    专栏名称 Prometheus 43 Grafana 实践派 专栏介绍 本专栏根据本公司统一监控落地实践编写 在该专栏您将学到 企业级监控的选型Prometheus的基础知识Grafana的基础知识快速搭建Prometheus 43 Gra
  • 泊松分布–计算概率分布的公式

    Probability Distributions play an important role in our daily lives We commonly use them when trying to summarise and ga
  • Prometheus 的介绍和安装

    介绍 Prometheus 是一个开源的监控和报警系统 最初由SoundCloud于2012年创建 随着越来越多的公司采用Prometheus以及非常活跃的社区 Prometheus于2016年加入云原生基金会 成为Kubernetes之后
  • 因为锁的问题,我们被扣了1万

    前言 春节放假期间 xff0c 一个项目上的积分接口被刷 xff0c 而且不止一个人在刷 xff0c 并且东西也被兑走 xff0c 放假晚上被人叫起来排查问题 xff0c 通过这个人的积分明细观察 xff0c 基本一秒就能获取一次 xff0