并发处理 Django乐观锁的实现

商品超卖问题:多个用户同时下单同一个商品时,可能会出现资源竞争问题,导致库存结果出现异常

乐观锁解决:

乐观锁并不是真正的锁,只是更新数据的时候多加一层判断

更新的时候判断此时库存是否和之前查询的库存一样,如果一样则表示没人修改,可以进行更新;否则表示有人抢过该资源,不再进行更新。类似下面操作:

update tb_sku set stock=2 where id=1 and stock=7;

SKU.objects.filter(id=1, stock=7).update(stock=2)

思路:

创建保存点

查询库存

更新库存时,将之前查询的库存和商品id一起作为更新的条件

当受影响行为0表示更新失败,回滚到保存点(没有操作数据库的时候)

重新查询,重复到n次不成功返回错误 (这里while True 直到库存为0停止)

示例:

from django.db import transaction

# 部分代码使用事物
with transaction.atomic():
    # 创建保存点
    save_id = transaction.savepoint()
    try:
        # 生成订单信息
        order = OrderInfo.objects.create(
            ...
        )
        # 从redis取购物车要结算的商品数据(省略写法)
        ...
        cart = {shu.id: sku_count, ...}
        
        while True: # 直到没有库存为止
            sku = SKU.objects.get(pk=sku_id)  # 不加锁查询
            # 购物车商品数量
            count = cart[shu.id]
            # 获取原始库存
            origin_stock = sku.stock
            # 判断商品库存是否充足
            if origin_stock < count:
                # 库存不足
                raise serializers.ValidationError('库存不足')
            
            # 演示并发请求
            import time
            time.sleep(5)

            # 记录原来的值
            origin_sales = sku.sales
            # 计算要更新的值
            new_stock = origin_stock - count
            new_sales = origin_sales + count

            # 返回受影响的行数
            ret = SKU.objects.filter(id=sku.id,stock=origin_stock).update(stock=new_stock,sales=new_sales)
            if ret == 0:
                # 更新成功,进入下次循环重新判断
                continue
            else:
                # 保存订单商品数据
                ...
                
                # 更新成功,退出while循环
                break    
            
            ...
            
    except Exception as e:
        # 提交保存点
        transaction.savepoint_rollback(save_id)
        raise serializers.ValidationError('下单失败')
    # 提交事务
    transaction.savepoint_commit(save_id)
    # 清除购物车中已经结算的商品
    ...
    return order

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值