概述
- 在多个用户同时发起对同一个商品的下单请求时,先查询商品库存,再修改商品库存,会出现资源竞争问题,导致库存的最终结果出现异常。
解决方法:
使用乐观锁或悲观锁
- 乐观锁
- 悲观锁
二、乐观锁
总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改。乐观锁并不是真实存在的锁,而是在更新的时候判断此时的库存是否是之前查询出的库存,如果相同,表示没人修改,可以更新库存,否则表示别人抢过资源,不再执行库存更新。
三、悲观锁
总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起。可以依靠数据库实现,如行锁、读锁和写锁等,都是在操作之前加锁。悲观锁类似于我们在多线程资源竞争时添加的互斥锁,容易出现死锁现象,采用不多。
四、例子
乐观锁:
'''乐观锁下订单(存在事务管理)'''
class TradeCommitView_le(View):
@transaction.atomic
def post(self, request):
'''设置保存点用于事务管理'''
sid1 = transaction.savepoint()
user = request.user
if not user.is_authenticated():
'''判断是否登陆'''
return redirect(reverse('car:index'))
# 接收数据
car_id = request.POST.get('car_id')
pay_method = request.POST.get('pay_style')
address_id = request.POST.get('address')
from datetime import datetime
order_id = str(user.id) + datetime.now().strftime('%Y%m%d%H%M%S')
# 运费(元)
transport = 5000
if not all([car_id, pay_method, address_id]):
return HttpResponse('数据内容不完整')
# 校验数据的正确(作业)
try:
car = CarDetail.objects.get(id=car_id)
except:
pass
service = float(car.car_price) * 10000 * 0.04
if service < 3000:
service = 3000
add = AddressInfo.objects.get(id=address_id)
# sid1 = transaction.savepoint()
# 创建订单
try:
order_new = OrderInfo.objects.create(
order_id=order_id,
user=user,
add=add,
price=car.car_price,
service_charge=service,
freight=transport,
# status = 0,
# pay_method =
online_pai_method=pay_method
)
#乐观锁。不是真正意思上的锁,只是在更新前查询,如果不符合条件就回滚,符合就继续执行。
res = CarDetail.objects.filter(id=car_id,status=1).update(status=0)
print('res',res)
if res == 0 :
transaction.savepoint_rollback(sid1)
return HttpResponse('车辆不存在')
order_car = OrderCar.objects.create(
oder=order_new,
car_id=car,
comment='')
except Exception as e:
transaction.savepoint_rollback(sid1)
return JsonResponse({'errmsg': e})
transaction.savepoint_commit(sid1)
return render(request,'trade_pay.html',context={'order_id':order_id})
悲观锁:
from django.db import transaction
'''悲观锁下订单(存在事务管理)'''
class TradeCommitView(View):
@transaction.atomic #装饰器的方法实现事务管理
def post(self,request):
'''设置保存点用于事务管理'''
sid1 = transaction.savepoint()
user = request.user
if not user.is_authenticated():
'''判断是否登陆'''
return redirect(reverse('car:index'))
# 接收数据
car_id = request.POST.get('car_id')
pay_method = request.POST.get('pay_style')
address_id = request.POST.get('address')
from datetime import datetime
order_id = str(user.id) + datetime.now().strftime('%Y%m%d%H%M%S')
# 运费(元)
transport = 5000
if not all([car_id,pay_method,address_id]):
return JsonResponse({'errmsg':'数据内容不完整'})
try:
# car = CarDetail.objects.get(id=car_id)
#悲观锁
car = CarDetail.objects.select_for_update().get(id=car_id)
except:
transaction.savepoint_rollback(sid1)
return HttpResponse('车辆不存在')
service = float(car.car_price) * 10000 * 0.04
if service < 3000:
service = 3000
add = AddressInfo.objects.get(id=address_id)
# sid1 = transaction.savepoint()
#创建订单
try:
order_new = OrderInfo.objects.create(
order_id = order_id,
user = user,
add = add,
price = car.car_price,
service_charge =service,
freight =transport,
# status = 0,
# pay_method =
online_pai_method = pay_method
)
import time
# time.sleep(30)
if car.status != 1: #如果车辆不是上线状态
transaction.savepoint_rollback(sid1) #回退到保存点
return JsonResponse({'errmsg':'下单失败'})
order_car =OrderCar.objects.create(
oder=order_new,
car_id = car,
comment='')
car.status = 0
car.save()
except Exception as e:
transaction.savepoint_rollback(sid1)
return JsonResponse({'errmsg':e})
transaction.savepoint_commit(sid1)
return HttpResponse('结束')
最后
以上就是迅速钢笔为你收集整理的python电商项目中,两个人同时购买库存为1的商品时怎么处理?的全部内容,希望文章能够帮你解决python电商项目中,两个人同时购买库存为1的商品时怎么处理?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复