Springboot:商品库存并发更新,乐观锁失败重试机制
一个商城项目,用户下单时需要更新商品库存,在商品类增加了version字段,增加乐观锁,保证库存数据的线程安全,但是在多个用户同时下单更新库存时可能会导致库存更新失败,因此需要增加乐观锁失败重试机制
一、相关代码
(1)商品实体类
@Data
@ApiModel(value = "Goods对象", description = "Goods对象")
public class Goods {@ApiModelProperty(value = "商品名称")private String name;@ApiModelProperty(value = "商品标题图")private String tittleImg;@ApiModelProperty(value = "商品数量")private Integer quantity;@ApiModelProperty(value = "展示价格")private BigDecimal price;@ApiModelProperty(value = "商品详情")private String details;@ApiModelProperty(value = "商品分类")private String category;@ApiModelProperty(value = "版本")@Versionprivate Integer version;
}
(2)失败重试注解类
import java.lang.annotation.*;@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FailRetry {//重试次数,这里默认15int value() default 15;
}
(3)重试切面类
import XXXX.exception.TryAgainException; //类的路径自行修改
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;@Aspect
@Configuration
@Slf4j
public class TryAgainAspect {/*** 定义切点*/@Pointcut("@annotation(com.ht.store.annotation.FailRetry)")private void failRetryPointCut() {}@Around("failRetryPointCut() && @annotation(failRetry)")@Transactional(rollbackFor = Exception.class)public Object retry(ProceedingJoinPoint joinPoint, FailRetry failRetry) throws Throwable {int count = 0;do {count++;try {log.info("重试次数:{}", count);return joinPoint.proceed();} catch (TryAgainException e) {if(count >= failRetry.value()){TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();throw new TryAgainException("重试失败");}}} while (true);}
}
(3)更新失败异常类
public class TryAgainException extends RuntimeException {public TryAgainException(String e) {super(e);}
}
(4)库存更新方法,注意方法上加上注解
@Override
@FailRetry
@Transactional(rollbackFor = TryAgainException.class)
public boolean updateGoodsQuantity(Long id,Integer number) {Goods goods = this.getById(id);goods.setQuantity(goods.getQuantity() - number);if (this.updateById(goods)){return true;}else{throw new TryAgainException("更新异常,版本号不一致");}
}
二、执行测试
数据库商品目前库存976,version是23
调用接口更新库存 -1
更新成功了,查看数据库
修改代码,模拟一次更新失败
@Override
@FailRetry
@Transactional(rollbackFor = TryAgainException.class)
public boolean updateGoodsQuantity(Long id,Integer number) {Goods goods = this.getById(id);goods.setQuantity(goods.getQuantity() - number);goods.setVersion(20); //此处修改为老版本,肯定更新失败if (this.updateById(goods)){return true;}else{throw new TryAgainException("更新异常,版本号不一致");}
}
更新时version是20,而数据库的version是24,会判定为老版本,表示已经被更新过,会更新失败,触发异常,然后去执行重试机制
抛出TryAgainException异常,数据回滚,由于方法有@FailRetry注解,进入注解绑定的切面类
注解类FailRetry里面默认15次,最多重试15次,结束重试。
一般情况下,每次更新前读取最新的,然后减掉库存进行更新,失败的次数不会太多,可以满足日常使用。
Springboot:商品库存并发更新,乐观锁失败重试机制相关推荐
- mysql乐观锁重试_乐观锁失败重试
1.乐观锁失败后会报:ObjectOptimisticLockFailureException 2.处理方案:捕获到对应乐观锁失败异常后进行重试,代码参考如下 在写入数据库的时候需要有锁,比如同时写入 ...
- Elasticsearch 并发修改乐观锁
2019独角兽企业重金招聘Python工程师标准>>> Elasticsearch 并发修改乐观锁 博客分类: 搜索引擎,爬虫 来自: http://blog.csdn.net//j ...
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
Java并发问题–乐观锁与悲观锁以及乐观锁的一种实现方式-CAS </h1><div class="clear"></div><div c ...
- invalid signature 错误原因验签失败_Nginx 失败重试机制
可直接点击上方蓝字 (网易游戏运维平台) 关注我们,获一手游戏运维方案 src 网易游戏 SRE,喜欢钻研与分享. 背景 Nginx 作为目前应用较广的反向代理服务,原生提供了一套失败重试机制,来保证 ...
- 自动化测试实例分享——《用例失败重试机制》
1. 背景说明 在开展自动化测试工作时,经常会由于一些外在原因(如网络中断.返回超时)导致自动化测试用例运行失败,而这些失败并不是用例本身验证或被测程序存在Bug而引起的,更可气的是这些失败场景有可能 ...
- mysql乐观锁重试_乐观锁加重试,并发更新数据库一条记录导致:Lock wait timeout exceeded...
背景: mysql数据库,用户余额表有一个version(版本号)字段,作为乐观锁. 更新方法有事务控制: @Transactional(rollbackFor = Exception.class) ...
- Springboot秒杀系统(乐观锁+RateLimiter令牌+Redis缓存)
本文主要是利用springboot,实现一个单机版秒杀demo,通过单机版实现,可以对基本并发秒杀的知识有一定的了解. 首先先提供秒杀业务实现类: /*** spring 注解加在实现类*/ @Ser ...
- jpa mysql乐观锁_【快学springboot】8.JPA乐观锁OptimisticLocking
介绍 当涉及到企业应用程序时,正确地管理对数据库的并发访问是至关重要的.为此,我们可以使用Java Persistence API提供的乐观锁定机制.它导致在同一时间对同一数据进行多次更新不会相互干扰 ...
- springboot 使用mybatis-plus 配置乐观锁。
-----------------------------官方文档已更新,详细配置请访问:mybatis plus乐观锁插件 进行查看--------------------------------- ...
最新文章
- 4岁的儿子还不会写红黑树,我该怎么办?
- Kali Linux WPScan更新到2.9.3
- CentOS 6.5 64位 安装Nginx, MySQL, PHP
- Android新手入门2016(15)--Gallery画廊
- 宏观经济之国家经济与建设
- nodejs连接redis,redis服务器的地址格式应该怎么写
- ROS环境下跑orb-slam2 单目相机
- 运行tomcat报Exception in thread ContainerBackgroundProcessor[StandardEngine[Catalina]]
- Android实例-拍摄和分享照片、分享文本(XE8+小米2)
- 高效、稳定开发功能的一些心得
- Django - 两周从入门到熟练工
- 编译OpenJDK8:specified bound depends on the length of the source argument
- 【转】Ubuntu 16.04安装配置TensorFlow GPU版本
- 计算机图形学——计算机图形系统及硬件基础
- 安吉丽娜-朱莉曝光罕见少女照(图)
- js调用Python函数
- [宋史学习] 宋初对党项的征讨与妥协
- 递归最小二乘法、增广最小二乘法、带遗忘因子的递归增广最小二乘法
- 面试题,互联网产品的盈利模式有哪些?
- 华为刀片服务器 安装文档,刀片服务器主机