如何保證冪等性


一、背景:

分布式場景下,接口的開發大都需要保證冪等性。

冪等性:一個接口被調用,不管幾次,產生一樣的效果,一樣返回結果。

接口調用過程中,很可能因為網絡等原因進行重試調用,如果不能保證冪等性,那就完犢子了。

例如:用戶支付的接口,用戶有可能連續點擊支付,總不能扣好幾次錢吧。

二、場景:

1、前端重復提交:

用戶快速重復點擊多次,造成后端生成多個內容重復的數據。

2、接口超時重試:

對於給第三方調用的接口,為了防止網絡抖動或其他原因造成請求丟失,這樣的接口一般都會設計成超時重試多次。

HTTP,RPC等在超時的情況下會有重試機制。

3、消息重復消費:

MQ消息中間件,消息重復消費。

三、冪等性方案:

冪等性的保證,很明顯無法通過一個方案解決所有問題,只能具體場景具體分析的。

1、業務表唯一索引:

對於數據插入的場景來說,這是最常見的方案。

核心業務字段設置為唯一索引,多次插入就會報錯,從而保證冪等性。

2、狀態流轉控制:

狀態流轉也是最常見的冪等性保證手段。

如配送業務中,騎手的操作肯定會對業務流轉狀態進行校驗。如果騎手已經提貨,那就肯定不能再次提貨的。

3、樂觀鎖版本號:

在業務表中新建一個字段version,int類型。

服務A調用服務B需要更新的時候,需要提前查詢到version,然后作為參數傳過去。

如果數據更新的時候將version + 1,接口如果發生重試的時候,version已經發生變更,那么也能保證冪等性。

PS:老實說,這個方案我本人沒用過,有點麻煩。大部分的更新不需要保證冪等性,最終的數據也能保證一致。

4、去重:

對於前端調用的接口,有些場景無法通過前面的方案保證冪等性。

接口中可以新增一個參數,這個參數保證每次請求都是唯一的。

然后將這個參數保存,每次請求的入參校驗都會查詢這個參數是否存在,如果存在就返回。

參數保存的方案可以是MySQL或者Redis。

對於本身並發較低的場景,不會對MySQL服務造成壓力,可以直接使用MySQL。否則,就要考慮Redis了,Redis這個key設置超時時間不用太長。

5、分布式鎖:

考慮到分布式環境下,很多方案的校驗如果無法保證串行的情況下,還是無法保證冪等性的。

例如,前面的狀態機校驗,並發環境下,可能還是會有問題,所以具體場景再進行分析。


免責聲明!

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



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