开始

image.png

提前写好的枚举类
image.png

  1. public enum OrderStatusEnum {
  2. WAIT_PAY(10,"代付款"),
  3. WAIT_DELIVER(20,"已付款,代发货"),
  4. WAIT_RECEIVE(30,"已发货,待收货"),
  5. SUCCESS(40,"交易成功"),
  6. CLOSE(50,"交易关闭");
  7. public final Integer type;
  8. public final String value;
  9. OrderStatusEnum(Integer type, String value) {
  10. this.type = type;
  11. this.value = value;
  12. }
  13. }

状态默认是等待付款
image.png
image.png

image.png

扣除库存

在 规格表内,有个库存
image.png

ItemSservice定义减少库存的方法,decrease是减少。stock是库存。
image.png

 /**
     *
     * @param specId
     * @param butCounts
     */
    public void decreaseItemSpecStock(String specId,Integer buyCounts);

事务,涉及到修改用required
image.png

库存对于所有用户来说,它是一个公共的资源,
image.png
比如当前库存是10,当有两三个查询都过来,查询都是10
image.png
真实的情况下 可能会同时减去这进来三个查询 ,那么库存就变成了负数。那么就成了数据的不一致性。
image.png

共享资源涉及到的数据一致性。

上海某小公司面试题:synchronized锁原理
https://juejin.cn/post/6921566403036200968

有的人可能会说只要在方法上加上关键字,加一个锁。的确可以保证资源不被多个线程共享。但是也会有问题。加上synchronized就是一个一个线程的去执行,效率性能就会比较低下。如果我们服务是个单体的服务, 可以保证当前问题是没有的。如果后续我们把单体服务发展成为集群了,那么就不会起作用了。每个服务之间还是会存在资源共享的问题。
image.png
有的人可能会说在数据库层面把这张表锁一下,如果万一出现问题, 这样也会造成数据库性能的低下。
image.png
分布式锁。
image.png

分布式锁,设计到zooker和redis都可以做分布式锁。
image.png
减去库存之前加锁和减锁
image.png

乐观锁

单体服务里面,我们使用乐观锁,直接通过sql语句去更新也是没有问题的
首先自定义sql语句
image.png
stock必须要大于等于 pendingCounts 。存量必须要大于减去的数量。这个update如果更新成功,mybatis会返回1,如果是0就是没有更新,没有更新成功就抛出异常。
image.png

<update id="decreaseItemSpecStock">
    update
    items_spec
    set stock = stock - #{pendingCounts}
    where
    id=#{specId}
    and
    stock > #{pendingCounts}
  </update>

由于事务在service抛出异常会被orderServie测试到,那么orderService里面所有的事务都会回滚
image.png
这样使用乐观锁,达到效果
image.png
ItemsMapperCustom
image.png

public int decreaseItemSpecStock(@Param("specId") String specId,
                                     @Param("pendingCounts") int pendingCounts);

image.png

 @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的循环里面的。
image.png

//2.4 用户提交订单以后,规格表中需要扣除库存
            itemService.decreaseItemSpecStock(itemSpecId,butCounts);

结束