天天看點

網際網路 API 接口幂等性設計

WEB 資源或 API 方法的幂等性是指一次和多次請求某一個資源應該具有同樣的副作用。幂等性是系統的接口對外一種承諾(而不是實作), 承諾隻要調用接口成功, 外部多次調用對系統的影響是一緻的。幂等性是分布式系統設計中的一個重要概念,對逾時處理、系統恢複等具有重要意義。聲明為幂等的接口會認為外部調用失敗是常态, 并且失敗之後必然會有重試。例如,在因網絡中斷等原因導緻請求方未能收到請求傳回值的情況下,如果該資源具備幂等性,請求方隻需要重新請求即可,而無需擔心重複調用會産生錯誤。實際上,我們常用的 HTTP 協定的方法是具有幂等性語義要求的,比如:get 方法用于擷取資源,不應有副作用,是以是幂等的;post 方法用于建立資源,每次請求都會産生新的資源,是以不具備幂等性;put 方法用于更新資源,是幂等的;delete 方法用于删除資源,也是幂等的。

常見用來保證幂等的手段:

1.MVCC 方案

  多版本并發控制,該政策主要使用 update with condition(更新帶條件來防止)來保證多次外部請求調用對系統的影響是一緻的。在系統設計的過程中,合理的使用樂觀鎖,通過 version 或者 updateTime(timestamp)等其他條件,來做樂觀鎖的判斷條件,這樣保證更新操作即使在并發的情況下,也不會有太大的問題。例如

select * from tablename where condition=#condition# // 取出要跟新的對象,帶有版本 versoin

update tableName set name=#name#,version=version+1 where version=#version#

  在更新的過程中利用 version 來防止,其他操作對對象的并發更新,導緻更新丢失。為了避免失敗,通常需要一定的重試機制。

2.去重表

  在插入資料的時候,插入去重表,利用資料庫的唯一索引特性,保證唯一的邏輯。

3.悲觀鎖

select for update,整個執行過程中鎖定該訂單對應的記錄。注意:這種在 DB 讀大于寫的情況下盡量少用。

  1. select + insert

      并發不高的背景系統,或者一些任務 JOB,為了支援幂等,支援重複執行,簡單的處理方法是,先查詢下一些關鍵資料,判斷是否已經執行過,在進行業務處理,就可以了。注意:核心高并發流程不要用這種方法。

5.狀态機幂等

  在設計單據相關的業務,或者是任務相關的業務,肯定會涉及到狀态機,就是業務單據上面有個狀态,狀态在不同的情況下會發生變更,一般情況下存在有限狀态機,這時候,如果狀态機已經處于下一個狀态,這時候來了一個上一個狀态的變更,理論上是不能夠變更的,這樣的話,保證了有限狀态機的幂等。

  1. token 機制,防止頁面重複送出

      業務要求:頁面的資料隻能被點選送出一次

      發生原因:由于重複點選或者網絡重發,或者 nginx 重發等情況會導緻資料被重複送出

    解決辦法:

叢集環境:采用 token 加 redis(redis 單線程的,處理需要排隊)

單 JVM 環境:采用 token 加 redis 或 token 加 jvm 記憶體

處理流程:

資料送出前要向服務的申請 token,token 放到 redis 或 jvm 記憶體,token 有效時間

送出後背景校驗 token,同時删除 token,生成新的 token 傳回

  token 特點:要申請,一次有效性,可以限流

  1. 對外提供接口的 api 如何保證幂等

      如銀聯提供的付款接口:需要接入商戶提傳遞款請求時附帶:source 來源,seq 序列号。source+seq 在資料庫裡面做唯一索引,防止多次付款,(并發時,隻能處理一個請求)

      總結: 幂等性應該是合格程式員的一個基因,在設計系統時,是首要考慮的問題,尤其是在像支付寶,銀行,網際網路金融公司等涉及的都是錢的系統,既要高效,資料也要準确,是以不能出現多扣款,多打款等問題,這樣會很難處理,使用者體驗也不好 。

轉載:https://www.cnblogs.com/wxgblogs/p/6639272.html

繼續閱讀