并发处理 Django乐观锁的实现
发布日期:2021-05-14 23:02:04 浏览次数:18 分类:精选文章

本文共 1859 字,大约阅读时间需要 6 分钟。

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

乐观锁解决:

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

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

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

 

上一篇:python django后端 跨域解决
下一篇:Java通过非常简单的方法打印任意行数的实心菱形和空心菱形

发表评论

最新留言

很好
[***.229.124.182]2025年04月24日 03时52分10秒