Mysql分布式锁(一)通过jvm本地锁解决mysql并发问题及可能的失效情况

news2024/12/26 0:16:35

强烈建议配合之前的JVM本地锁(一)简单实现阅读

mysql场景

将之前的场景修改为mysql场景,即在数据库中保存一条数据,多个线程并发处理该数据。

数据库建表如下

在这里插入图片描述

pom.xml中新增mybatis-plus和mysql

		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.4.3.4</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

application.yml

配置文件中配置好mysql的地址和用户名密码

server:
  port: 10010
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://xxxx:3306/distributed_lock
    username: root
    password: 123

Stock

@TableName("db_stock")
@Data
public class Stock {
    private Long id;
    private String productCode;
    private String warehouse;
    private Integer count;
}

StockMapper

@Mapper
public interface StockMapper extends BaseMapper<Stock> {
}

StockService

@Service
public class StockService {

    @Autowired
    private StockMapper stockMapper;

    public void deduct(){
        Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("product_code","1001"));
        if(stock != null && stock.getCount() > 0){
            stock.setCount(stock.getCount()-1);
            stockMapper.updateById(stock);
        }
    }
}

StockController

@RestController
public class StockController {
    @Autowired
    private StockService stockService;

    @GetMapping("stock/deduct")
    public String deduct(){
        stockService.deduct();
        return "hello stock deduct";
    }
}

启动后,修改下Jmeter的http request地址
在这里插入图片描述
再进行测试
在这里插入图片描述

由于需要数据库连接访问,吞吐量明显降低,182。
再看数据库该条数据的count是否清0

在这里插入图片描述
并不是0,并发引起了超卖问题。

JVM本地锁解决mysql并发问题

synchronized

直接用JVM本地锁,加上synchronized

@Service
public class StockService {

    @Autowired
    private StockMapper stockMapper;

    public synchronized void deduct(){
        Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("product_code","1001"));
        if(stock != null && stock.getCount() > 0){
            stock.setCount(stock.getCount()-1);
            stockMapper.updateById(stock);
        }
    }
}

重启后,把数据库count修改为5000,再次测试
在这里插入图片描述
吞吐量惨不忍睹,16。
再看数据库,成功清0
在这里插入图片描述

ReentrantLock

简单修改StockService即可

@Service
public class StockService {

    @Autowired
    private StockMapper stockMapper;

    private ReentrantLock lock = new ReentrantLock();

    public void deduct(){
        lock.lock();
        try{
            Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("product_code","1001"));
            if(stock != null && stock.getCount() > 0){
                stock.setCount(stock.getCount()-1);
                stockMapper.updateById(stock);
            }
        }finally {
            lock.unlock();
        }
    }
}

重启后,把数据库count修改为5000,再次测试

在这里插入图片描述
吞吐量较synchronized略提升,22。
再看数据库
在这里插入图片描述

问题解决。

mysql中JVM本地锁不生效的三种情况

1. 多例模式

默认情况下,service controller等class都是单例模式,可以通过添加注解成为多例模式

@Service
@Scope(value = "prototype",proxyMode = ScopedProxyMode.TARGET_CLASS)
public class StockService {

重启,修改count数据后再测试
在这里插入图片描述
无错误,再看数据库
在这里插入图片描述
count并没有清0。
因为多例模式,不同线程访问的可能是不同的service实例,那你锁的其实只是一部分,而不是所有的。

2.事务

在deduct方法上添加事务注解@Transactional

@Service
public class StockService {

    @Autowired
    private StockMapper stockMapper;

    private ReentrantLock lock = new ReentrantLock();

    @Transactional
    public void deduct(){
        lock.lock();
        try{
            Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("product_code","1001"));
            if(stock != null && stock.getCount() > 0){
                stock.setCount(stock.getCount()-1);
                stockMapper.updateById(stock);
            }
        }finally {
            lock.unlock();
        }
    }
}

重新测试。
在这里插入图片描述
在这里插入图片描述
依然有问题,这是为什么呢?
举例,如果有两个线程A B同时请求,假设现在count为91

A访问B访问
A获取锁
A查询count:91
A扣减count:90
释放锁
B获取锁
B查询count:91
A提交事务
B扣减count:90
B释放锁
B提交事务

很明显,count为91,AB两个线程并发请求后,只变成了90

根本问题还是先释放锁再提交事务,不能保证原子性。

如果设置事务的隔离级别为 READ_UNCOMMITTED就可解决该问题,但是你读取别人未提交的事务,别人的事务很有可能还会回滚,就会造成脏读问题,所以不能使用READ_UNCOMMITTED。

3. 集群部署

类似多例模式,但还是有所不同。

1) 将服务新增一个端口启动。

在这里插入图片描述

在这里插入图片描述
两个服务都启动成功。

2) nginx负载均衡

修改nginx.conf

vi /usr/local/etc/nginx/nginx.conf

在这里插入图片描述

修改完后重启nginx

brew services restart nginx

3)修改jmeter测试端口为80

4)重新测试

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
很明显看见,有处理同一个库存数现象
数据库也未清0
在这里插入图片描述

总结一下:

jvm本地锁有三种情况后导致锁失效

  1. 多例模式
  2. 事务
  3. 集群部署

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

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

相关文章

戴尔r730xd服务器从u盘启动设置方法(戴尔r730取消网络启动方法)

1,开机后出现提示的时候&#xff0c;按F12 2,等一会系统会自动进入BIOS选择菜单:选择system bios 回车 3,这时在选择boot setting 回车: 4,在这里选择 BIOS Boot settings 5,将网卡启动的勾选去掉&#xff0c;即默认使用C盘启动 6,退出Esc&#xff0c;会提示保存&#xff0…

C#语言实例源码系列-电脑系统挂机锁

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…

[附源码]Python计算机毕业设计广西助农平台Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

微服务框架 SpringCloud微服务架构 多级缓存 46 JVM 进程缓存 46.2 导入商品案例【导入Demo工程】

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 多级缓存 文章目录微服务框架多级缓存46 JVM 进程缓存46.2 导入商品案例【导入Demo工程】46.2.1 导入商品管理案例demo工程46 JVM 进程缓存 …

你知道吗?Python原来可以做这些

如果你准备开始学习Python或者你已经开始了学习Python&#xff0c;那么&#xff0c;你肯能会问自己&#xff1a; “我用Python究竟能做些什么&#xff1f;” 嗯&#xff0c;这是一个棘手的问题&#xff0c;因为Python有很多应用方向。但随着时间的推移&#xff0c;我发现Pytho…

Java图书管理代码

Java图书管理代码一&#xff1a;简介二&#xff1a;核心需求三: 类的设计1. 创建图书相关的类2. 创建操作相关的类3. 创建用户相关的类4. 进行整合5. 实现具体的每个 Operation大家好&#xff0c;我是晓星航。今天为大家带来的是Java语言图书馆里系统的相关的讲解&#xff01;&…

【裂缝识别】无人机裂缝图像处理系统(带面板)【含GUI Matlab源码 1727期】

⛄一、简介 1 案例背景 随着国家对公路建设的大力投入&#xff0c;我国的公路通车总里程己经位居世界前列&#xff0c;这样进一步促进了我国经济建设的发展。随着公路的大量投运&#xff0c;公路日常养护和管理已经成为制约公路运营水平提高的瓶颈&#xff0c;特别是路面状态采…

使用QtDesignerForm界面

使用QtDesignerForm界面1. 概述2. UI文件的使用分析2.2 QtDesignerForm 界面的使用3. Demo1. 概述 在进行QT开发创建UI文件通常有两种方式&#xff0c;分别是通过Qt 设计师界面类、Qt Designer Form创建。两者创建的区别如下。 通过Qt 设计师界面类创建的界面通常会包括对应的…

手把手系列:如何将小程序游戏引入自有APP?(iOS篇)

自FinClip 诞生以来&#xff0c;一直有不少开发者询问官方 FinClip 什么时候可以支持微信小游戏&#xff1f;实际上&#xff0c;从去年开始我们就把支持微信小游戏的计划做进了产品的 Roadmap。2022年底&#xff0c;我们终于在新年之前实现了对小游戏的支持&#xff01; 近期…

中文输入法中光标跟随能力触发的浏览器事件探究

:::tip 最近在着手腾讯文档的输入体验优化&#xff0c;在其中有一个不起眼的小需求引起了我的注意&#xff0c;并顺便研究了一些事件监听机制相结合的特点&#xff0c;特此记录一下填坑过程。 ::: 模拟光标跟随 大部分的主流输入法都有这样一个特性&#xff0c;在输入中文时&…

昆仑天工开源的AIGC

🍿*★,*:.☆欢迎您/$:*.★* 🍿 https://github.com/SkyWorkAIGC/SkyCode 技术优势一 :涵盖多种编程语言 不同的编程语言着重于解决不同平台、环境下的问题,不同的编程语言都有自己存在的理由。奇点智源SkyCode能够生成的代码,不仅包括使用广泛的JavaScript、python、Jav…

(六)springcloud之Nacos集群与持久化配置-3

模块&#xff1a; 1.父工程&#xff08;管理版本&#xff09; 2.公共模块&#xff1a;Common-API 3.测试模块&#xff1a;NacosClusterConfigConsumer80 版本&#xff1a; springboot:2.7.6 springcloud:2021.0.5 spring-cloud-alibaba-dependencies:2021.0.1.0 nacos:2.1.2 ng…

RCFSNet

搬来了一种结合道路上下文信息与多尺度特征的道路遥感图像道路提取方法&#xff0c;与常见的道路提取算法相比&#xff0c;RCFSNet能够获取完整的路网标签&#xff0c;在遮挡场景中表现出色 本人是太原理工大学大数据学院在2022年发表在《IEEE Geoscience and remote sensing …

SpringBoot网站开发常用工具类(自己写的适合入门)

目录 字符集转换工具 适用 代码 JWT工具类 适用 代码 七牛云文件上传工具类 适用 代码 文件类型转换工具类 适用 代码 session&#xff0c;cookie工具类 适用 代码 字符集转换工具 适用 主要是完成与前端配合&#xff0c;共同实现特殊字符串传输过程中被转译的问…

数字藏品系统应用场景介绍——元宇宙NFG

数字藏品系统应用场景&#xff1a; 1.虚实结合产品营销&#xff1a;品牌企业限量发行产品&#xff0c;比如限量珍藏版产品&#xff0c;茅台酒&#xff0c;耐克鞋&#xff0c;劳力士手表&#xff0c;爱马仕包包&#xff0c;钻石珠宝&#xff0c;结合元宇宙热点营销&#xff0c;…

Crane 发布国内首个云原生应用碳排放计算优化器

为了共同应对气候变化挑战&#xff0c;减缓全球变暖趋势&#xff0c;2015年12月&#xff0c;近200个缔约方共同通过了《巴黎协定》&#xff08;The Paris Agreement&#xff09;&#xff0c;对2020年后全球如何应对气候变化做出了行动安排。为实现这一目标&#xff0c;全球多个…

我国液化石油气行业SWOT分析:产销规模持续上涨 供需缺口劣势明显

液化石油气是在炼油厂内&#xff0c;由天然气或者石油进行加压降温液化所得到的一种无色挥发性液体,它极易自燃&#xff0c;当其在空气中的含量达到了一定的浓度范围后&#xff0c;它遇到明火就能爆炸。 一、优势分析 根据观研报告网发布的《中国液化石油气市场发展深度分析与…

【Unity】UI ToolKit 学习记录

Unity推出的这个 UI ToolKit&#xff0c;据说是要用来替代UGUI。既然这么有野心&#xff0c;那肯定要搞来看一看。这次使用目标就是用这个 UI ToolKit 生成一堆类似HUD的头标&#xff0c;然后看看使用难易程度和性能如何。 本文对应Unity版本 &#xff1a;2020.3.41f1c1 1、安装…

四十六——五十一

四十六、JavaScript——对象 一、对象 数据类型&#xff1a;原始值&#xff1a; 1. 数值 Number 2. 大整数 BigInt 3. 字符串 String 4. 布尔值 Boolean 5. 空值 Null 6. 未定义 Undefinded 7. 符号 Symbol 除了七种原始值之外&#xff0c;后面所用到的数据类型&#xff0c;都…

吐槽嫌弃测试周期太长?开发自测一下

互联网产品竞争激烈&#xff0c;在生存的巨大压力之下&#xff0c;策划和运营人员们恨不得每一个需求都能秒级上线&#xff0c;这就给研发团队带来了巨大的压力。 有时候&#xff0c;产品的老大很关注某一个功能点&#xff0c;希望能尽快上线&#xff0c;可是&#xff0c;他发…