日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

商城商品超卖处理

發布時間:2024/1/17 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 商城商品超卖处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先環境介紹下:商城商品可能存在幾個端(PC、APP),其次每個端對應的服務端又可能做了負載均衡(即也有多個服務端)。

要實現的目標和功能:保證商品不會出現超賣的情況。超賣商品后,無法對商品進行發貨,是一種不負責任的行為。

方案實現討論流程

“要實現不超賣,首先商品庫存的扣減不能使用框架進行更新,因為框架是設置值,如果在這段時間,又有人購買了,則商品庫存必然會出現問題。要采用手寫SQL方式。并且sql中還要判斷是否大于等于指定的購買量。”

UPDATE `SKU_Info` SET skuNum=skuNum-1000 WHERE id='00293cb7-d8cf-4470-a66d-bb45ca2b130000293cb7-d8cf-4470-a66d-bb45ca2b1300' AND skuNum>=1000;

“要實現不超賣,我們可以對方法加上同步鎖,這樣可以解決”。

“方法加上同步鎖后,用戶下單將會出現排隊的情況,性能有問題。”

“那我們可以實現對同一商品進行加鎖,這樣可以解決購買不同商品不會相互阻塞。如果有包含關系,也應該加鎖。比如A用戶購買商品1和商品2,B用戶購買商品1,因為他們都有商品1,則應該加鎖。”

“你這個方案應該可以解決問題,采用分布式鎖的方式可以解決,我們可以使用redis來做。”

“是的,確實可以解決問題,并且多個服務端也不存在問題了,就這么干。”

“我們可以對訂單中的所有商品的sku值進行排序,拼接成一個skuId值,然后MD5的值作為key,其它訂單進來方法時,按同樣的操作進行檢測是否正在下單,如果是,則等待。”

“你這種方案忽略了商品不同的情況,就比如上面的例子中,A購買商品1和商品2,B購買商品1,那么他們的key是不同的,因而達不到效果。”

“我們可以對每個商品sku的id定義個鎖,這樣每次購買時,我們針對每個商品進行檢測,這樣就可以了,絕對能夠保證同步。”

“這種方法可行,不過還是存在一個問題,服務端與redis的連接次數會比較多,如果一個用戶下單商品種類較多,那么仍然會比較慢,但這確實不失為一個好的方案。”

“既然這個方案仍然有可能有問題,那么還有沒有其它的方案。”

“數據庫本身是有鎖的,可以實現鎖同步的問題,那么有沒有辦法使用到數據庫的鎖來解決這個問題?”

“對呀,我們可以寫SQL語句去循環扣減庫存,最后判斷數據庫影響行數與商品種類是否匹配?如果不匹配,則是扣減失敗,進行還原,如果匹配,則扣減成功!”

“經過測試,我們用的MySQL不支持這種方案,里面需要用到if判斷,而if判斷必須要在存儲過程中才能使用。”

“那我們可以使用存儲過程來做。代碼如下”

DELIMITER $$ USE anke_skucenter$$ CREATE PROCEDURE minusSkuNum() BEGIN SET AUTOCOMMIT=0; START TRANSACTION; UPDATE SKU_Info SET skuNum=skuNum-100 WHERE id='0031394c-8058-49f5-9ba9-f971480ac2f2' AND skuNum>=100;IF(SELECT ROW_COUNT()<=0)THENROLLBACK;END IF; UPDATE `SKU_Info` SET skuNum=skuNum-1000 WHERE id='00293cb7-d8cf-4470-a66d-bb45ca2b130000293cb7-d8cf-4470-a66d-bb45ca2b1300' AND skuNum>=1000; IF(SELECT ROW_COUNT()<=0)THENROLLBACK; END IF; COMMIT; SET AUTOCOMMIT=1; END$$

?“這個是初步的存儲過程,仍然需要將update語句變更為循環,改變傳入參數為商品id和數量,有誰會寫?”

“額,目前大家都不會寫,并且這個循環看上去也挺復雜的。”

“那么我們能不能在mybatis中獲取多條更新語句的影響行數?”

“不能,沒有任何框架支持,并且mysql本身就不支持,要不然也不會需要存儲過程了。”

“既然多條SQL不行,能不能放到一條SQL中去做更新呢?”

“先baidu下”

“哈哈,找到了,我們查詢的時候有時候回用到case when,那么我們更新的時候是否可以使用這個呢?嘗試代碼如下:”

update SKU_Info set skuNum=skuNum-(case when id='0031394c-8058-49f5-9ba9-f971480ac2f2' then 100 when id='00293cb7-d8cf-4470-a66d-bb45ca2b1300' then 1000 end) where (id='0031394c-8058-49f5-9ba9-f971480ac2f2' AND skuNum>=100) or (id='00293cb7-d8cf-4470-a66d-bb45ca2b1300' AND skuNum>=1000);

?“經過測試,該段代碼執行正常,并且能夠正常返回需要的影響行數。”

“這個循環的SQL編寫在mybatis中不難,那么判斷最后扣減結果與商品種類不同時,如何進行補償呢?”

“這個可以使用@Transactional,我們在方法上加此注解,在方法內部判斷,如果不同,我們就拋出一個自定義異常,這樣就會自動進行回滾了。”

“測試一下”

“經過幾輪測試,確實可行,就這樣做。”

“具體實施為:先生成訂單,然后進行扣減,如果捕獲到扣減失敗的自定義異常,則對生成的訂單執行刪除標記。但存在一個問題,就是標記訂單為刪除狀態失敗的情況,這個訂單仍然存在,也是超賣了。”

“可以調整下,改為先進行扣減,扣減成功再生成訂單,這樣可以避免此問題。”

“嗯,此方法可以解決超賣問題,可能會存在商品扣減成功,但訂單未生成的情況。”

“這種問題會存在,但比超賣要好很多。”

“嗯嗯”

“嗯嗯”

轉載于:https://www.cnblogs.com/maomao999/p/9223721.html

總結

以上是生活随笔為你收集整理的商城商品超卖处理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。