django實(shí)現(xiàn)悲觀鎖樂觀鎖的項(xiàng)目實(shí)踐
前期準(zhǔn)備
# 線上賣圖書 -圖書表 圖書名字,圖書價(jià)格,庫存字段 -訂單表: 訂單id,訂單名字 # 表準(zhǔn)備 class Book(models.Model): name = models.CharField(max_length=32) price = models.IntegerField() # count = models.SmallIntegerField(verbose_name='庫存') class Order(models.Model): order_id = models.CharField(max_length=64) order_name = models.CharField(max_length=32) # 使用mysql DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'lqz', 'HOST': '127.0.0.1', 'PORT': '3306', 'USER': 'lqz', 'PASSWORD': '123', } } # 創(chuàng)建lqz數(shù)據(jù)庫
1.原生mysql悲觀鎖
begin; # 開啟事務(wù) select * from goods where id = 1 for update; # 行鎖 # order表中加數(shù)據(jù) update goods set stock = stock - 1 where id = 1; # 更新 commit; #提交事務(wù)
2.orm實(shí)現(xiàn)上述(悲觀鎖)
#1 使用悲觀鎖實(shí)現(xiàn)下單 @transaction.atomic # 整個(gè)過程在一個(gè)事物中---》改兩個(gè)表:book表減庫存,訂單表生成記錄 def seckill(request): # 鎖住查詢到的book對(duì)象,直到事務(wù)結(jié)束 sid = transaction.savepoint() # 保存點(diǎn) # 悲觀鎖: select_for_update() # 加鎖了--》行鎖還是表鎖? 分情況,都有可能 # book = Book.objects.select_for_update().filter(pk=1).first() # 加悲觀鎖,行鎖,鎖住當(dāng)前行 if book.count > 0: print('庫存可以,下單') # 訂單表插入一條 Order.objects.create(order_id=str(datetime.datetime.now()), order_name='測(cè)試訂單') # 庫存-1,扣減的時(shí)候,判斷庫存是不是上面查出來的庫存,如果不是,就回滾 time.sleep(random.randint(1, 4)) # 模擬延遲 book.count=book.count-1 book.save() transaction.savepoint_commit(sid) # 提交,釋放行鎖 return HttpResponse('秒殺成功') else: transaction.savepoint_rollback(sid) #回滾,釋放行鎖 return HttpResponse('庫存不足,秒殺失敗')
3 樂觀鎖秒殺--》庫存還有,有的人就沒成功
# 2 樂觀鎖秒殺--普通版 @transaction.atomic def seckill(request): # 鎖住查詢到的book對(duì)象,直到事務(wù)結(jié)束 sid = transaction.savepoint() book = Book.objects.filter(pk=1).first() # 沒加鎖 count = book.count print('現(xiàn)在的庫存為:%s' % count) if book.count > 0: print('庫存可以,下單') Order.objects.create(order_id=str(datetime.datetime.now()), order_name='測(cè)試訂單-樂觀鎖') # 庫存-1,扣減的時(shí)候,判斷庫存是不是上面查出來的庫存,如果不是,就回滾 # time.sleep(random.randint(1, 4)) # 模擬延遲 res = Book.objects.filter(pk=1, count=count).update(count=count - 1) if res >= 1: # 表示修改成功 transaction.savepoint_commit(sid) return HttpResponse('秒殺成功') else: # 修改不成功,回滾 transaction.savepoint_rollback(sid) return HttpResponse('被別人改了,回滾,秒殺失敗') else: transaction.savepoint_rollback(sid) return HttpResponse('庫存不足,秒殺失敗')
到此這篇關(guān)于django實(shí)現(xiàn)悲觀鎖樂觀鎖的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)django 悲觀鎖樂觀鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python標(biāo)準(zhǔn)庫pickle的簡(jiǎn)單使用
本文主要介紹了Python標(biāo)準(zhǔn)庫pickle的簡(jiǎn)單使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05django開發(fā)教程之利用緩存文件進(jìn)行頁面緩存的方法
緩存相信對(duì)各位程序員們來說都不陌生,下面這篇文章主要給大家介紹了關(guān)于django開發(fā)教程之利用緩存文件進(jìn)行頁面緩存的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11Python Celery異步任務(wù)隊(duì)列使用方法解析
這篇文章主要介紹了Python Celery異步任務(wù)隊(duì)列使用方法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08

python編寫softmax函數(shù)、交叉熵函數(shù)實(shí)例

Python中實(shí)現(xiàn)定時(shí)任務(wù)常見的幾種方式

mvc框架打造筆記之wsgi協(xié)議的優(yōu)缺點(diǎn)以及接口實(shí)現(xiàn)