Redis应用之二分布式锁2

一、前言

前一篇 Redis应用之二分布式锁  我们介绍了使用SETNX来实现分布式锁,并且还遗留了一个Bug,今天我们对代码进行优化,然后介绍一下Redisson以及数据库的乐观锁悲观锁怎么用。

二、SetNX分布式锁优化后代码

RedisService.java

InventoryMgrImpl.java

将代码部署在两台机器,库存设置为10000, set "inventory:9321785256118"  10000,然后Jemter创建两个线程组,每个线程组起500个线程,循环执行10次,结果库存值为0,没有产生并发问题。注(这里每一次调用扣减一个库存)。

注意点

1、设置锁的超时时间,超时时间不能设置太短,一定要比业务代码执行耗时最长的时间再大一些,一般设置为3秒差不多,上一篇文章用了Redis分布式锁还产生问题的原因就是因为超时时间设置太短造成的,业务代码还未执行完,锁就失效被另外一个线程持有然后在并发量大的情况就产生问题了。另外老版本Redis的SetNX好像是不能设置超时时间,这个就必须自己去控制超时以避免死锁。

2、代码中当获取锁失败立即重新去获取这个会对redis造成冲击,可以加入适当的休眠时间。

三、使用Redisson实现Redis分布式锁

Redisson是一个基于Redis扩展库,提供了很多具有分布式环境特性的常用工具类,我们这里用来使用它分布式锁机制。

1、加入依赖包

2、配置类

3、代码中获取锁

用100个线程两台机器压测,未产生并发问题。

注:高版本JDK(比如JDK17)Redisson运行时报错,原因未确认。

以上不管是自己直接调用SetNX,还是用Redisson做分布式锁都是基于单台Redis的,如果是集群Redis会更复杂一些。

四、数据库锁

数据库锁也分为乐观锁和悲观锁,这种方案在传统软件公司会采用比较多一些,互联网公司一般不太采用数据库的特性去做事情,主要是数据库负载相对来讲比较大,会尽量避免。

1、乐观锁

认为数据一般不会发生冲突,在数据提交更新时才会去检查数据是否冲突,如果冲突不执行返回错误。

具体实现:通过给表加一个version字段来实现,当读取数据时,将version字段的值一起读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断当前version与开始取出来的版本值大小是否相等,如果相等,则予以更新,否则认为出现并发问题不更新数据,让用户重新操作。

创建库存表

SpringBoot整合JDBC

InventoryManagerDB.java

不用数据库锁,Jmeter开启两组线程,每组1个线程,循环500次,最终库存数据是208,肯定会产生并发问题。

代码中加上乐观锁

1、数据库增加version字段

2、InventoryManagerDB.java

Jmeter开启两组线程,每组1个线程,循环500次,最终库存数如下

这说明有307次变更库存是失败的,693次变更成功,但没有发生并发问题,因为直接告诉用户失败了或者让用户采用重试机制。

2、悲观锁

对数据的冲突采取悲观的态度,也就是假设数据肯定会冲突,所以在数据开始读取的时候,就把数据锁定住,此时当其他事务如果要更新此条记录就会因为不能获得锁而阻塞。

注意:这里查询的时候用主键然后加上for update锁定这条记录,并且该方法要加上@Transactional事务控制,如果不是使用主键可能就把整张表锁住了。

Jmeter开启两组线程,每组50个线程,循环10次,最终库存数据是0,未产生并发问题。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python数据容器之[列表]

Python数据容器 Python中的数据容器: 一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素 每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。 数据容器根据特点的不同,如: 是否支…

Python数据容器(序列操作)

序列 1.什么是序列 序列是指:内容连续、有序。可以使用下标索引的一类数据容器 列表、元组、字符串。均可以视为序列 2.序列的常用操作 - 切片 语法:序列[起始下标:结束下标:步长]起始下标表示从何处开始,可以留空,留空视作从…

python 根据经纬度绘制点图 极投影

参考了python cartopy手动导入地图数据绘制底图/python地图上绘制散点图:Downloading:warnings/散点图添加图里标签_python add_feature-CSDN博客 点的颜色按照时间显示 # -*- coding: utf-8 -*- """ Created on Mon Nov 13 11:32:48 2023"&quo…

数据结构—数组栈的实现

前言:各位小伙伴们我们前面已经学习了带头双向循环链表,数据结构中还有一些特殊的线性表,如栈和队列,那么我们今天就来实现数组栈。 目录: 一、 栈的概念 二、 栈的实现 三、 代码测试 栈的概念: 栈的概念…

TSINGSEE视频智能分析人员入侵AI检测算法如何让城市管理更加高效、智慧?

在城市管理场景中,经常面临着禁区垂钓、非法捕捞、行人闯红灯、小区盗窃、车辆乱停乱放等一系列管理难题,这给城市发展带来了不小的阻力,同时也极易增加管理的人力、物力和财力。传统的人员巡逻监管效率低并且存在时间差,很难及时…

2023年数维杯国际大学生数学建模挑战赛

当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2022年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。 cs数模团队在数维杯前为大家提供了许多资料的内容呀&#xff0…

Python 如何实现 Command(命令)模式?什么是 Command(命令)设计模式?

什么是命令设计模式? 命令模式(Command Design Pattern)是一种行为设计模式,它将请求封装成一个对象,从而允许参数化客户端对象,排队请求,或者对请求进行操作。命令模式支持撤销操作&#xff0…

傅里叶分析(2)

在《傅里叶分析(1)》中,讲述了连续信号的傅里叶分析方法,本文讲述离散信号的傅里叶分析方法。 虽然电、声、光、机械振动等信号在物理上是连续函数,但在实际工程中,其通常为离散信号,即若干离散…

设计模式之模版方法(TemplateMethod)

模版方法 钩子函数 回调函数 在父类里面有一个模版方法,在这个方法里面调用了op1,op2,op3… 在子类里面如果想要改变父类的op1和op2 只需要重写op1和op2,那么这个重写之后的方法,可以在父类里面直接调用的到 例子: J…

ctfshow sql171-179

mysql 先打开我们本地的mysql,可以看到这些数据库 information_schema information_schema 库: 是信息数据库,其中保存着关于MySQL服务器所维护的所有其他数据库的信息比如数据库名,数据库表, SCHEMATA表: 提供了当前MySQL实例…

Linux下MSSQL (SQL Server)数据库无法启动故障处理

有同事反馈一套CentOS7下的mssql server2017无法启动需要我帮忙看看,启动报错情况如下 检查日志并没有更新日志信息 乍一看mssql-server服务有问题,检查mssql也确实没有进程 既然服务有问题,那么我们用一种方式直接手工后台启动mssql引擎来…

22.构造一个关于员工信息的结构体数组,存储十个员工的信息

结构体问题。构造一个关于员工信息的结构体数组,存储十个员工的信息,包括员工工号,员工工资,员工所得税,员工实发工资。要求工号和工资由键盘输入,并计算出员工所得税(所得税工资*0.2&#xff0…

C语言--1,5,10人民币若干,现在需要18元,一共有多少种?

今天小编给大家分享一下穷举法的一道典型例题 一.题目描述 1,5,10人民币若干,现在需要18元,一共有多少种? 二.思路分析 总共有18块钱,设1元有x张,5元有y张,10元有z张,则有表达式:x5y10z18,穷举法最重要的…

java网络编程之UDP协议

文章目录 UDP简介一发一收客户端:服务端: 多发多收实现多开客户端:服务端 UDP简介 UDP(User Datagram Protocol) DatagramSocket 用于创建客户端、服务端DatagramSocket() :创建客户端的Socket对象,系统随…

Java 算法篇-深入了解单链表的反转(实现:用 5 种方式来具体实现)

🔥博客主页: 小扳_-CSDN博客 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 单链表的反转说明 2.0 单链表的创建 3.0 实现单链表反转的五种方法 3.1 实现单链表反转 - 循环复制(迭代法) 3.2 实现单链表反转 - 头插法 3…

什么是浏览器指纹?指纹浏览器如何避免浏览器指纹的追踪识别?

在做独立站跨境电商的过程中,海外社交媒体平台已成为我们必不可少的交易渠道。但是,由于各大平台对账号管理极其严格,对账户进行严密监控也成为了常态。这当然与浏览器指纹识别有关,今天龙哥就给大家科普一下什么是浏览器指纹&…

Autosar模块介绍:Memory_4(EA-EE抽象)

上一篇 | 返回主目录 | 下一篇 Autosar模块介绍:Memory_4(EA-EE抽象 1 基本术语解释2 Ea组成结构图3 Ea基本操作3.1 通用操作3.2 作业的进程(通用需求)3.3 读操作过程3.4 写操作过程3.5 擦除过程3.6 比较过程 4 Ea常用操作时序4.1 初始化4.2…

如何搞垮一个测试团队?

要想彻底搞垮一个测试团队并非易事,需要多角色通力配合、多方联动、综合施策,才能达到目的。 本文从实践经验出发,为大家总结了搞垮测试团队的18项措施,或许可以给大家带来一些启发。 — 1 — QA QA作为质量管理者,…

轻量封装WebGPU渲染系统示例<29>- 深度模糊DepthBlur(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/DepthBlur.ts 当前示例运行效果: 此示例基于此渲染系统实现,当前示例TypeScript源码如下: const blurRTTTex0 { diffuse: { uuid: "rtt0", …

【vue】虚拟dom的原理是什么?手写实现虚拟dom !

1.虚拟dom的原理 虚拟 DOM 是对 DOM 的抽象,本质上就是用 JavaScript 对象来描述 DOM 结构。Vue.js 中关于虚拟 DOM 的实现主要进行了以下几个步骤: 1.生成虚拟 DOM: Vue.js 使用 render 函数来依据模板代码生成虚拟 DOM。在这个过程中&a…