為什麼加了鎖還是出現庫存扣超的情況

2021-09-29 22:34:48 字數 886 閱讀 2365

最近碰到乙個需求,庫存扣減,要保證在高併發情況下不出問題。

第一想到的就是redis分布式鎖,為了保證原子操作,加鎖和解鎖都使用lua指令碼,但是在壓力測試的時候發現,tps只有個位數,而且成功率不好控制,我是自己控制嘗試獲取鎖的次數,因此造成了大量的執行緒阻塞。

後面找了一些資料,改為redisson,tps能達到100以上,成功率在90%以上,以為就此完結,後來自己做測試的時候發現資料總是有誤,這裡再提一下,業務並不是直接扣減庫存,而是預扣減,我的做法是增加一條預扣減庫存記錄,在確認扣減後再進行真正的庫存扣減,所以在每次有預扣減前先查詢預扣減記錄,用實際的庫存減去預扣減記錄之和後才是剩下的庫存,但是在壓測的情況下(100個執行緒迴圈10次,測試工具為jmeter),庫存明明只有乙個,居然出現多餘一條的預扣減記錄,也就是說實際庫存是不夠減的,排除了鎖的問題,最後發現其實是插入預扣減庫存記錄的事務沒有及時提交(用的orm是spring-data-jpa),也就是說,第乙個執行緒進來,插入了一條預扣減庫存資料,但是並沒有立即提交這個事務,然後釋放鎖,第二個執行緒進來查詢預扣減資料並沒有查到第乙個執行緒插入的那條資料,於是庫存資料就出錯了。

在網上找了很多資料,找到了一種解決方案,就是spring的事務監聽,等待事務提交後再釋放鎖,讓新的執行緒進來,就不會出錯了。

transactionsynchronizationmanager.registersynchronization(new transactionsynchronizationadapter() 

});

把查詢與插入操作抽取到乙個單獨的方法中並加上事務註解,然後加上上面的這段**,就可以保證在高併發下庫存的正確性。

當然,這個監聽也是個同步方法,會一直等待事務提交,所以效能上有些許的下降,但還能接受,至少在分布式部署的情況下高併發也不會出現庫存錯誤的問題。

為什麼還是不敏捷

敏捷現在的確很火,特別是隨著網際網路應用開發的火熱,敏捷更是各個公司都在推崇的開發方法,什麼敏捷管理,敏捷開發,敏捷文化,方方面面都跟敏捷掛鉤,各個專案都在使用 站式晨會 迭代增量 結對程式設計 等敏捷實踐,但是我們大多數的團隊為什麼還是沒有真正的實現敏捷了,主要原因如下 一 捨本逐末,光顧著敏捷了...

session是什麼?為什麼出現?

當訪問伺服器某個網頁的時候,會在伺服器端的記憶體裡開闢一塊記憶體,這塊記憶體就叫做session,而這個記憶體是跟瀏覽器關聯在一起的。這個瀏覽器指的是瀏覽器視窗,或者是瀏覽器的子視窗,意思就是,只允許當前這個session對應的瀏覽器訪問,就算是在同乙個機器上新啟的瀏覽器也是無法訪問的。而另外乙個瀏...

為什麼會出現死鎖

今天在閱讀 我在思考乙個 如何可以抵擋得住大的迸發量,我先羅列我應該會設計的方案,然後再分析其中實現應該注意的地方 首先如果資料量很大的話,我們是要分散請求的,也就是需要伺服器來聯合作戰,當然這裡我們就需要有乙個好的輪詢的演算法,不然會出現資料無法保持一致而導致程式中隱藏bug,所以說,考慮的方面不...