使用乐观锁解决超卖问题的代码实现

问题:下单成功的条件是什么?
结果:首先库存大于购买量,然后更新库存和销量时原始库存没变。
结论:所以在用户库存满足的情况下,如果更新库存和销量时原始库存有变,那么继续给用户下单的机会。

实现代码

# 2, 订单提交
class OrderCommitView(MyLoginRequiredMixin):
    @transaction.atomic
    def post(self, request):
        # 1,获取参数
        dict_data = json.loads(request.body.decode())
        address_id = dict_data.get("address_id")
        pay_method = dict_data.get("pay_method")

        # 2,校验参数
        # 2,1 为空校验
        if not all([address_id, pay_method]):
            return http.JsonResponse({"code": RETCODE.NODATAERR, "errmsg": "参数不全"})

        # 2,2 地址是否存在
        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            return http.JsonResponse({"code": RETCODE.NODATAERR, "errmsg": "地址不存在"})

        # 2,3 支付方式校验
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM["CASH"], OrderInfo.PAY_METHODS_ENUM["ALIPAY"]]:
            return http.JsonResponse({"code": RETCODE.NODATAERR, "errmsg": "支付方式有误"})

        # 3,数据入库
        # 3,1 订单编号
        user = request.user
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + "%09d%s" % (random.randint(0, 999999999), user.id)

        # 3,2 订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM["CASH"]:
            status = OrderInfo.ORDER_STATUS_ENUM["UNPAID"]
        else:
            status = OrderInfo.ORDER_STATUS_ENUM["UNSEND"]

        # TODO 设置保存点
        sid = transaction.savepoint()

        order_info = OrderInfo.objects.create(
            order_id=order_id,
            user=request.user,
            address=address,
            total_count=0,
            total_amount=Decimal(0.0),
            freight=Decimal(10.0),
            pay_method=pay_method,
            status=status
        )

        # 3,3 获取redis中需要结算的商品
        redis_conn = get_redis_connection("carts")
        cart_dict = redis_conn.hgetall("carts_%s" % user.id)
        selected_list = redis_conn.smembers("selected_%s" % user.id)

        # 4 遍历,创建订单商品数据
        for sku_id in selected_list:
            # 4.1 获取sku对象,数量
            sku = SKU.objects.get(id=sku_id)
            count = int(cart_dict[sku_id])

            # 4,2 判断库存是否充足
            if count > sku.stock:
                transaction.savepoint_rollback(sid)  # TODO 回滚
                return http.JsonResponse({"code": RETCODE.NODATAERR, "errmsg": "库存不足"})

            # 4,3 减少库存,增加销量
            sku.stock -= count
            sku.sales += count
            sku.save()

            # 4,4 创建订单商品对象
            OrderGoods.objects.create(
                order=order_info,
                sku=sku,
                count=count,
                price=sku.price
            )

            # 4,5 累加数量,和价格到订单信息表
            order_info.total_count += count
            order_info.total_amount += int(count * sku.price)

        # 5,保存订单信息表
        order_info.save()
        transaction.savepoint_commit(sid)  # TODO 提交

        # 6,清空redis
        redis_conn.hdel("carts_%s" % user.id, *selected_list)
        redis_conn.srem("selected_%s" % user.id, *selected_list)

        # 7,返回响应
        return http.JsonResponse({"code": RETCODE.OK, "errmsg": "下单成功"})
发布了53 篇原创文章 · 获赞 69 · 访问量 1930
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览