重復支付問題如何解決(悲觀鎖和樂觀鎖)


用戶確認支付后,支付系統異步調用交易系統,交易系統更新交易狀態,通知商家發貨。如果交易系統超時未響應支付系統,支付系統會進行重試。有可能這時交易系統已經通知商家發貨,這次的重試會讓商家發貨兩次,這是不可以接受的。
image

這時,需要引入一個防重操作,例如,每次更新交易狀態,先查詢是否是初始狀態,如果是,就更新為成功,並且通知商家發貨。如果不是初始狀態,就不通知商家發貨。以下是偽代碼演示:

1.select * from order_info where id = "20201020"
2.Java代碼判斷status == '初始' 執行3,否則返回
3.update order_info set status = '成功' where id = '20201020'並且發貨

上面的防重操作並沒有考慮並發的情況,當有兩個請求都執行了1,都拿到初始狀態,他們就都會去通知發貨。

悲觀鎖方案

查詢時加行鎖。

begin transaction
1.select * from order_info where id = "20201020" for update 加record lock
2.Java代碼判斷status == '初始' 執行3,否則返回
3.update order_info set status = '成功' where id = '20201020'並且發貨
commit

樂觀鎖方案

在update時加一個state = '初始'條件,如果state為初始,則影響行數為1,如果state為成功,則影響行數為0。通過最后一個更新操作的影響行數來判斷是否返回。

begin transaction
1.select * from order_info where id = "20201020" for update 加record lock
2.Java代碼判斷status == '初始' 執行3,否則返回
3.update order_info set status = '成功' where id = '20201020' and state = '初始',判斷影響行數,若為1則發貨
commit

OS:我尋思這不是重復發貨嗎。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM