1. 什麼是幂等問題?
舉個最簡單的例子,那就是支付,使用者購買商品後支付,支付扣款成功,但是傳回結果的時候網絡異常,此時錢已經扣了,使用者再次點選按鈕,此時會進行第二次扣款,傳回結果成功,使用者查詢餘額發現多扣了錢,流水記錄也變成了兩條。
2. 怎麼保證幂等性?
通過代碼邏輯判斷實作接口幂等性,隻能針對一些滿足判斷的邏輯實作,具有一定局限性。
原始版本
boolean pay(int accountid,BigDecimal amount) //用于付款,扣除使用者的
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iNlJDZxMDN4MGMiFTM4EGOzYTY5YTNlhTNzQmZkJWM18CX0EzLchDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL1M3Lc9CX6MHc0RHaiojIsJye.png)
這種情況下,支付系統已經扣款,但是訂單系統因為網絡原因,沒有擷取到确切的結果,是以訂單系統需要重試。由上圖可見,支付系統并沒有做到接口的幂等性,訂單系統第一次調用和第二次調用,使用者分别被扣了兩次錢,不符合幂等性原則(同一個訂單,無論是調用了多少次,使用者都隻會扣款一次)。如果需要支援幂等性,付款接口需要修改為以下接口:
幂等版本
boolean pay(int orderId,int accountId,BigDecimal amount)
通過orderId來标定訂單的唯一性,付款系統隻要檢測到訂單已經支付過,則第二次調用不會扣款而會直接傳回結果
使用token機制實作接口幂等性,通用性強的實作方法。
token機制實作步驟:
生成全局唯一的token,token放到redis或jvm記憶體,token會在頁面跳轉時擷取.存放到pageScope中,支付請求送出先擷取token
送出後背景校驗token,執行送出邏輯,送出成功同時删除token,生成新的token更新redis ,這樣當第一次送出後token更新了,頁面再次送出攜帶的token是已删除的token背景驗證會失敗不讓送出
token特點: 要申請,一次有效性,可以限流
注意: redis要用删除操作來判斷token,删除成功代表token校驗通過,如果用select+delete來校驗token,存在并發問題,不建議使用
Distributed - 分布式鎖
參考文獻
接口幂等性