zoukankan      html  css  js  c++  java
  • 乐观锁实现电商网站秒杀

    
    
    from django_redis import get_redis_connection


    class
    OrderCommitView(view):
      @transaction.atomic
      def post(self, request):
        # 判断用户是否登录
        user = request.user
        if not user.is_authenticated():
          return JsonResponse("res":0,"error_msg":"用户未登录"
    )
        
        addr_id = request.POST.get('addr_id')
        pay_method = request.POST.get('pay_methon')
        sku_ids = request.POST.get('sku_ids')
        
        if not all([addr_id, pay_method, sku_ids]):
          return JsonResponse({'res':1, 'error_msg':'params not enough'})

        # 校验支付方式
        if pay_method not in OrderInfo.PAY_METHODS.keys():
          return JsonResponse('ret':2,'error_msg':'非法支付方式')

        # 校验地址
        try:
          addr = Address.objects.get(id=addr_id)
        except Address.DoesNotExist:
          return JsonResponse('ret':3,'error_msg':"地址非法")

        # 创建订单核心业务
        订单id :日期加用户的id
        order_id = datetime.now().strftime("%Y%m%d%H%M%S")+str(user.id)

        # 运费
        transit_price = 10

        # 总数目总金额
        total_count = 0
        total_price = 0
        
        # 设置事物保存点
        save_id = transaction.savepoint()
        try:
          # todo 向df_oeder_info表中添加一条记录
          order = OrderInfo.objects.create(order_id=order,user=user,pay_method=pay_method,total_count=total_count,total_price=total_price)
          conn = get_redis_connection('default')
          cart_key = 'cart_%d'%user.id
          sku_ids = sku_ids.split(',')
          for sku_id in sku_ids:
            # 获取商品信息
            # for 循环3次 尝试都能下单成功
            for i in range(3):
              try:
                sku = GoodsSKU.objects.get(id=sku_id)
              except:
                # 商品不存在
                transaction.savepoint_rollback(save_id)
                return JsonResponse({'ret':4,'error_msg':"商品不存在"})
            

              # 从redis中获取用户需要购买的商品的数量
              count = conn.hget(cart_key,sku.stock)
              # todo 判断商品的库存
              if int(count) > sku.stock:
                transaction.savepoint_rollback(save_id)
                return JsonResponse({'res':6,'error_msg':'商品库存不足'})
              # todo 更新商品的库存和销量
              origin_stock = sku.stock
              new_stock = origin_stock - int(count)
              new_sales = sku.sales + int(count)
            
                   print('user:%s,stock:%s'%(user.id,sku.stock))
              import time
              time.sleep(10)

      # upload df_goods_sku set stock=new_stock,sales=new_sales where id=sku_id and stock=origin_stock
       #乐观锁 res返回受影响的行数
              res = GoodsSKU.objects.filter(id=sku_id,stock=origin_stock).update(stock=new_stock.sales=new_sales)
              if res == 0:
                if i ==2:
                  transactin.savepoint_rollback(save_id)
                  return JsonResponse({'res':7,'error_msg':"下单失败2})
                continue
              # todo 向df_order_goods表中添加一条记录
              OrderGoods.objects.create(order=order,
                           sku=sku,count=count,price=sku.price)
              # todo 累加计算订单商品的总数量和总价格
              amount = sku.price*int(count)
              total_count += int(count)
              total_price += amount
              break
          # todo更新订单信息表中的商品的总数量和总价格
          order.total_count = total_count
          order.total_price = total_price
          order.save()
        except Exception as e:
          transaction.savepoint_rollback(save_id)
          return JsonResponse('res':7,'error_msg':'下单失败')
        # 提交事务
        transaction.savepoint_commit(save_id)
        # 提交事务
        conn.hdel(cart_key,*sku_ids)

        # 返回应答
        return JsonResponse({'res':5,'message':'创建成功'})


    最后一步:

    乐观锁需要将数据库(MYSQL)的默认隔离程度可重复读(读的是第一次读到的数据),所以需要将MySQL的隔离级别更改为读已提交
    打开MySQL的配置文件 sudo vi /etc/mysql/mysqlconf.d/
    修改为读已提交
    transaction_isolation = READ_COMMITTED
    重启MySQL:sudo service mysql restart
  • 相关阅读:
    【NOIP2007】守望者的逃离
    20200321(ABC)题解 by 马鸿儒 孙晨曦
    20200320(ABC)题解 by 王一帆
    20200319(ABC)题解 by 王一帆 梁延杰 丁智辰
    20200314(ABC)题解 by 董国梁 蒋丽君 章思航
    20200309(ABC)题解 by 梁延杰
    20200307(DEF)题解 by 孙晨曦
    20200306(ABC)题解 by 孙晨曦
    20200305(DEF)题解 by 孙晨曦
    20200303(ABC)题解 by 王锐,董国梁
  • 原文地址:https://www.cnblogs.com/tangda/p/12348174.html
Copyright © 2011-2022 走看看