美文网首页
高并发库存减扣方案

高并发库存减扣方案

作者: 夜色001 | 来源:发表于2020-09-25 18:31 被阅读0次

一、概述

电商平台中,订单模块的一个非常重要的点就是防止商品超卖。什么叫商品超卖,就是用户显示下单成功,但库存因为并发的原因扣减成了负数,造成实际商品量不足,无法发货。如果用户已支付,则需要进行退款操作。

二、解决思路

【解决思路】对下单流程进行加锁,同一时间仅支持一个线程进行下单。

三、解决方案

1、对下单流程加锁

这种方式对整个下单流程进行加锁,简单粗暴,但弊端非常明显。比如一个请求处理时间为100ms,1000个人请求,响应时间就达到了100s,1分钟以上,用户很难接受。

2、利用数据库行锁

【原理】
当对字段进行修改时,数据库会加一个行锁,我们将修改的条件设置成(库存-订单商品数>=0)。如果修改成功,即修改记录数大于0,则下单成功;否则库存不足,抛出异常,利用事务进行回滚。
注意:没有索引的时候,就是表锁,所以我们一定要加索引。通常建表时约定必须要有主键Id,即可避免,详细说明可以参考链接:https://blog.csdn.net/u013043762/article/details/80454396
【适合场景】
该模式对数据库的压力比较大,小量的并发可以满足。
当库存充足,并发量高时,会存在后续用户响应时间长的问题。
当库存较少,并发量高时,虽然不会再执行创建订单的逻辑,但是每个用户都在对数据库进行查询,依然存在数据库压力较大的问题。
【关键代码】

    @Override
    @Transactional
    public void order() {
        //减扣库存:成功后再增订单
        storeDeduction(1L, 3);
        //新增订单
        TblOrderEntity entity = new TblOrderEntity();
        saveEntity(entity);
        //新增订单详情
        TblOrderDetailEntity detailEntity = new TblOrderDetailEntity();
        detailEntity.setGoodId(1L);
        detailEntity.setGoodCount(3);
        detailEntity.setOrderId(entity.getId());
        tblOrderDetailService.saveEntity(detailEntity);
    }

    //库存减扣
    private void storeDeduction(Long goodId, Integer count) {
        //查询库存
        TblGoodEntity goodEntity = tblGoodService.getById(goodId);
        if (goodEntity.getStoreCount() > count) {
            //减扣库存
            Integer consumeStock = tblGoodService.consumeStock(goodId, count);
            if (consumeStock <= 0) {
                throw new OpenException("库存不足");
            }
        } else {
            throw new OpenException("库存不足");
        }
    }

    <update id="consumeStock">
        update tbl_good set store_count = store_count - #{count} where id=#{goodId} and store_count &gt;= #{count}
    </update>

3、

四、压力测试

相关文章

网友评论

      本文标题:高并发库存减扣方案

      本文链接:https://www.haomeiwen.com/subject/fewfuktx.html