一. 冪等的概念
用在編程領(lǐng)域里, 則意為: 對同一個系統(tǒng)壕曼,使用同樣的條件,一次請求和重復(fù)的多次請求對系統(tǒng)資源的影響是一致的。
在數(shù)學(xué)的定義里可以簡單理解為: 在某運算下,冪等元素是指被自己重復(fù)運算的結(jié)果等于它自己的元素。 f(x) = f(f(x))
二. 冪等的場景
在我們實際的開發(fā)過程中, 例如: 支付接口調(diào)用, 交易下單等.
有以下場景:
系統(tǒng)B接口不支持冪等, A系統(tǒng)請求B系統(tǒng)支付接口進(jìn)行支付. 因網(wǎng)絡(luò)超時導(dǎo)致接口請求失敗.
三. 關(guān)于接口的冪等設(shè)計
關(guān)于以上場景, A系統(tǒng)進(jìn)行后續(xù)處理.
如果將接口請求判為失敗, 顯然是不合理的. 因為,可能是在B系統(tǒng)接收到支付請求之后,進(jìn)行了扣款操作且扣款成功, 但是在接口返回時超時.
此時如果A系統(tǒng)再向B系統(tǒng)發(fā)起支付申請重試, 對于客戶來說同一筆交易發(fā)生多次扣款, 造成客戶損失.如果將接口請求判為成功, 也不合理. 因為,可能B系統(tǒng)根本就沒有接收到支付請求, 客戶也沒法發(fā)生扣款操作, 而客戶的訂單狀態(tài)卻成功了. 對于商戶來說會造成損失.
-
所以, 對與以上情況,都是不可取的. 正確的方式是:
- B系統(tǒng)在接口設(shè)計時, 定義一個對于每筆訂單都是唯一的流水號編號字段, 同時在DB中對該字段維護(hù)唯一約束.
- 若A請求B網(wǎng)絡(luò)超時, 那么A可以不更換交易流水號, 繼續(xù)請求B系統(tǒng)對超時的交易進(jìn)行重試. B系統(tǒng)在插入支付訂單前, 先檢查一下是否之前已經(jīng)處理該筆交易.
如果未處理, 則直接交易落地, 并進(jìn)行后續(xù)處理.
如果交易已處理,則返回給A系統(tǒng)此時的交易狀態(tài)和結(jié)果.
假設(shè)在接口請求時發(fā)生并發(fā), B系統(tǒng)也可以通過DB的唯一約束擋住另一筆并發(fā)的交易.
四. 關(guān)于接口防并發(fā)的處理方式
1.在接口方法上使用同步鎖
- 優(yōu)缺點: 實現(xiàn)簡單. 但是只適用于非集群環(huán)境
2.分布式鎖如redis
- 優(yōu)缺點: 能擋住分布式系統(tǒng)的并發(fā), 但是設(shè)計相對復(fù)雜(具體實現(xiàn)可以參考:分布式鎖的實現(xiàn)).而且控制并發(fā)的代價是讓接口在集群中都是單線程形式處理業(yè)務(wù)請求, 大大犧牲的接口性能. 并不可取
2.業(yè)務(wù)字段加唯一約束
- 優(yōu)缺點: 簡單實用, 但是需要另外維護(hù)該業(yè)務(wù)字段的生成規(guī)則(具體實現(xiàn)可以參考:分布式系統(tǒng)下如何生成唯一有序編號).
- 前端系統(tǒng)生成唯一性token+后端token字段落地并加唯一約束
- 優(yōu)缺點: 方便實用
對客戶端請求排隊或者單線程都可以處理并發(fā)冪等問題,需要根據(jù)具體業(yè)務(wù)選擇合適的方案但必須前后端一起做,前端做了可以提升用戶體驗秸应,后端則可以保證數(shù)據(jù)安全。
五. 總結(jié)
//TODO
參考文章
如有問題,還請各位老師批評指正,謝謝~