利用CAS减库存问题

项目背景

优惠券数量有限,多个用户同时获取优惠券需要考虑并发问题,这里我采用的是CAS算法来实现。

框架

  • springboot
  • jpa

核心代码

    @Transactional(rollbackOn = Exception.class)
    public void buy2(String name, int buyQuantity) {

        Product product = otherService.getByName(name);
        int result = reduceStorage(buyQuantity, product);

        // 模拟处理业务时间
        try {
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        while (result == 0) {
            // 如果失败一直重试
            Product pd = otherService.getByName(name);
            if (product.getQuantity() > buyQuantity) {
                result = reduceStorage(buyQuantity, pd);
            } else {
                System.out.println("库存不足");
                return;
            }
        }

    }
    @Modifying
    @Query("update Product roduct set quantity = ?2 where id = ?1 and quantity = ?3 and ?2 > 0")
    int updateQuantity(int id, int newQuantity, int oldQuantity);

说明:

  1. 重新查询数据库时,必须确保能够读取到其他事务提交的数据,要求数据库的事务隔离级别至少是read committed(读已提交)
  2. 另外因为这里是内部方法调用,必须考虑spring事务传播机制,需要用到注解@Transactional(Transactional.TxType.NOT_SUPPORTED),意思是不支持spring事务传播,也就是说这个方法是一个单独的事务
  3. 另外一点是同一个bean内单独事务不生效,所以要把这个方法提取到其他bean中。

补充:
oracle数据库默认事务隔离级别:READ_COMMITTED
mysql数据库默认事务隔离级别:REPEATABLE_READ
mysql的隔离级别比oracle高

参考链接
https://blog.csdn.net/qq315737546/article/details/76850173
https://www.cnblogs.com/yougewe/p/7466677.html
完整源码地址
https://github.com/hejiancao/ThreadSummary

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值