当前位置: 首页 > news >正文

SpringCloud系列 - 分布式锁(八)

目录

一、案例引入

1.1 模拟并发安全问题

1.2 解决办法:加锁!

二、锁失效情况

1.1 错误使用本地锁

1.2 集群模式下本地锁失效

1.3 单实例微服务中本地锁的风险​

三、解决办法

3.1 调整sql语句

3.2 分布式锁

四、基于Redis的分布式锁

4.1 介绍

4.2 Redisson

4.2.1 导入依赖

4.2.2 创建配置类

4.2.3 lock锁

(1)思考

(2)小结

4.2.4 lock锁 - 公平锁

4.2.5 lock锁 - 读写锁

(1)演示

(2)小结

4.2.6 信号量

4.2.7 闭锁

五、疑问解答

5.1 单体应用需要使用分布式锁吗

5.2 为什么实际工作代码中很多写操作都不加锁

5.3 有了分布式锁,还需要引入数据库锁吗?

5.4 有了分布式锁还需要本地锁吗


一、案例引入

1.1 模拟并发安全问题

创建一张数据库表,库存表,我们暂且只记录一条记录。

调用/stock/reduce接口,模拟实现减库存

减库存业务逻辑如下:

首先查询数据库中指定商品在目标仓库的当前库存量。

当确认该商品库存存在且数量大于零时,再执行库存扣减操作。

启动项目,我们通过调用该接口,模拟试一试!

我们连续点击了10次,按理说数据库减少库存10件,还剩4990,我们查看一下

没有问题。可见在没有并发调用时,接口一切正常。

但是并发情况下呢?

接下来先把数据库的剩余库存改回5000,我们通过jmeter模拟一下并发:

开启100个线程,每个线程执行50次,按理说,就可以把5000库存清零。

通过jmeter的聚合报告,发现5000次全部执行完成,未出现异常

我们看看数据库的变化

未清零,还剩4487,出现并发安全问题

这是为什么呢?

每个请求都可视为独立的线程。当这些线程并发执行时,由于库存修改操作需要时间处理,在某个特定时刻,多个查询线程可能会获取到相同的库存数量值,从而导致数据一致性问题。

1.2 解决办法:加锁!

将数据库数据还原5000,重新模拟并发:

可以看到,我们加上锁以后,吞吐量变小了。但是是否就解决了并发安全问题呢?看看库存量是否清零就行了。

还剩2488,并没有清零。不是说加锁就可以解决吗?

其实啊,原因在这里。

我们加上了@Transactional事务注解,上面这段代码的执行顺序变成了

开启事务 -> 获取锁 -> 执行业务代码 -> 解锁 -> 事务提交

事务默认是在方法执行前开启,方法结束后提交。然而我们的锁加在了这个方法的内部,导致当前事务尚未提交时就释放了锁,其他线程趁机进入了该方法执行操作,从而引发数据安全问题。

所以不加事务是不会有这个问题的,但通常情况下,我们是会选择使用@Transactional注解的,保证事务一致性。所以还有一个方法:可以修改一下执行顺序。例如:

执行效率上明显更慢了,但是并发安全问题得到了保障!

二、锁失效情况

1.1 错误使用本地锁

像前面的案例,我们一开始把锁加在事务方法内部,导致事务还未提交就解锁了,引发了并发安全问题。

1.2 集群模式下本地锁失效

当我们某个应用部署了多个实例,搭建集群,这种情况下本地锁也会导致失效。

多实例下并发竞争问题更明显,前面单体单实例部署的解决方案用普通锁,但在多实例下是行不通的。因为普通锁不能跨进程生效

我们举个例子演示一遍就知道了

使用Nginx进行负载均衡。

这里我们就使用window版的,这样方便些,启动前修改配置文件nginx.conf

然后启动Nginx,打开jmeter进行压测。记得数据库库存改回去。

可以看到集群模式,我们的吞吐量上来了,但是并发安全问题还是没有解决,也就是本地锁失效!

1.3 分布式(微服务)架构琐

所以说,集群模式下也好,分布式架构下包括微服务也好,并发情况下,本地锁都会有并发安全问题。

那么微服务系统每个服务只有一台机器呢?,一旦牵扯到服务之间的调用,只要

http://www.dtcms.com/a/273352.html

相关文章:

  • html页面,当鼠标移开A字标就隐藏颜色框
  • Spring Boot项目中大文件上传的优化策略与实践
  • 华为鸿蒙3.0 4.0完全关闭纯净模式的方法以及临时绕过纯净模式检测的方法
  • 接口(上篇)
  • 基于深度学习的自动调制识别网络(持续更新)
  • 亚洲牧原:活跃行业交流,延伸公益版图,市场拓展再结硕果
  • 布隆过滤器原理
  • 我的世界模组开发——机械动力的渲染(4)
  • java-io流
  • 对象序列化与反序列化
  • 【PyTorch】PyTorch 自动微分与完整手动实现对比
  • vue3 element plus table 使用固定列,滑动滚动会错位、固定列层级异常、滑动后固定列的内容看不到了
  • Java多线程 V1
  • AIStarter 3.2.0正式上线!高速下载+离线导入+一键卸载新功能详解【附完整使用教程】✅ 帖子正文(字数:约 400 字)
  • 静态路由综合实验
  • WiFi技术深度研究报告:从基础原理到组网应用与未来演进
  • python+django/flask基于微信小程序的农产品管理与销售APP系统
  • CTFshow-PWN-栈溢出(pwn62-pwn64)
  • JAVA面试宝典 -《新潮技术:协程与响应式编程实践》
  • 【Ubuntu】编译sentencepiece库
  • next.js打包后的前端资源如何进行部署和访问,为什么没有index.html
  • Vue响应式原理六:Vue3响应式原理
  • Java 17 新特性解析:密封类与模式匹配的完美协作
  • 01背包问题总结
  • 三维旋转沿轴分解
  • AWS ECS任务角色一致性检查与自动修复工具完全指南
  • LVGL学习笔记-----进度条控件(lv_bar)
  • Java结构型模式---桥接模式
  • 什么?不知道 MyBatisPlus 多数据源(动态数据源)干什么的,怎么使用,看这篇文章就够了。
  • AI探索 | 豆包智能助手跟扣子空间(AI办公助手)有什么区别