开始
提前写好的枚举类
public enum OrderStatusEnum {
WAIT_PAY(10,"代付款"),
WAIT_DELIVER(20,"已付款,代发货"),
WAIT_RECEIVE(30,"已发货,待收货"),
SUCCESS(40,"交易成功"),
CLOSE(50,"交易关闭");
public final Integer type;
public final String value;
OrderStatusEnum(Integer type, String value) {
this.type = type;
this.value = value;
}
}
状态默认是等待付款
扣除库存
在 规格表内,有个库存
ItemSservice定义减少库存的方法,decrease是减少。stock是库存。
/**
*
* @param specId
* @param butCounts
*/
public void decreaseItemSpecStock(String specId,Integer buyCounts);
事务,涉及到修改用required
库存对于所有用户来说,它是一个公共的资源,
比如当前库存是10,当有两三个查询都过来,查询都是10
真实的情况下 可能会同时减去这进来三个查询 ,那么库存就变成了负数。那么就成了数据的不一致性。
共享资源涉及到的数据一致性。
上海某小公司面试题:synchronized锁原理
https://juejin.cn/post/6921566403036200968
有的人可能会说只要在方法上加上关键字,加一个锁。的确可以保证资源不被多个线程共享。但是也会有问题。加上synchronized就是一个一个线程的去执行,效率性能就会比较低下。如果我们服务是个单体的服务, 可以保证当前问题是没有的。如果后续我们把单体服务发展成为集群了,那么就不会起作用了。每个服务之间还是会存在资源共享的问题。
有的人可能会说在数据库层面把这张表锁一下,如果万一出现问题, 这样也会造成数据库性能的低下。
分布式锁。
分布式锁,设计到zooker和redis都可以做分布式锁。
减去库存之前加锁和减锁
乐观锁
单体服务里面,我们使用乐观锁,直接通过sql语句去更新也是没有问题的
首先自定义sql语句
stock必须要大于等于 pendingCounts 。存量必须要大于减去的数量。这个update如果更新成功,mybatis会返回1,如果是0就是没有更新,没有更新成功就抛出异常。
<update id="decreaseItemSpecStock">
update
items_spec
set stock = stock - #{pendingCounts}
where
id=#{specId}
and
stock > #{pendingCounts}
</update>
由于事务在service抛出异常会被orderServie测试到,那么orderService里面所有的事务都会回滚
这样使用乐观锁,达到效果
ItemsMapperCustom
public int decreaseItemSpecStock(@Param("specId") String specId,
@Param("pendingCounts") int pendingCounts);
@Transactional(propagation = Propagation.REQUIRED)
@Override
public synchronized void decreaseItemSpecStock(String specId, Integer buyCounts) {
// synchronized 不推荐使用,集群下无用,性能低下
// 锁数据库:不推荐 导致数据库性能低下
// 分布式锁 涉及到zookeeper 和 redis
// lockUtil.getLock() --枷锁,假设有个lockUtil的工具类
//1.查询库存
// int stock=10;
// //2.判断库存,是否能减少到0一下
// if(stock-butCounts<0){
// //提示库存不足
// }
// lockUtil.unlock() --解锁
int result = itemsMapperCustom.decreaseItemSpecStock(specId, buyCounts);
if(result!=1){
throw new RuntimeException("订单创建失败!");
}
}
orderService扣除库存。
注意是在foreach的循环里面的。
//2.4 用户提交订单以后,规格表中需要扣除库存
itemService.decreaseItemSpecStock(itemSpecId,butCounts);