保證介面冪等性

2021-09-14 03:37:34 字數 1485 閱讀 9835

冪等性:其實就是資料一致性和事務完整性

數學上的定義:f(f(x))=f(x)。x被函式f作用一次和作用無限次的結果是一樣的。冪等性應用在軟體系統中,可以把它簡單定義為:某個函式或者某個介面使用相同引數呼叫一次或者無限次,其造成的後果是一致的,在實際應用中一般針對於介面進行冪等性設計。例如:

冪等需要通過唯一的業務單號來保證。也就是說相同的業務單號,認為是同一筆業務。使用這個唯一的業務單號來確保,後面多次的相同的業務單號的處理邏輯和執行效果是一致的。 下面以支付為例,在不考慮併發的情況下,實現冪等很簡單:①先查詢一下訂單是否已經支付過;②如果已經支付過,則返回支付成功;如果沒有支付,進行支付流程,修改訂單狀態為『已支付』。

上述的保證冪等方案是分成兩步的,第②步依賴第①步的查詢結果,無法保證原子性的。在高併發下就會出現下面的情況:第二次請求在第一次請求第②步訂單狀態還沒有修改為『已支付狀態』的情況下到來。既然得出了這個結論,餘下的問題也就變得簡單:把查詢和變更狀態操作加鎖,將並行操作改為序列操作。

如果只是更新已有的資料,沒有必要對業務進行加鎖,設計表結構時使用樂觀鎖,一般通過version來做樂觀鎖,這樣既能保證執行效率,又能保證冪等。例如: update tab1 set col1=1,version=version+1 where version=#version# 。但是,樂觀鎖存在失效的情況,就是常說的aba問題。如果version版本一直是自增的就不會出現aba的情況

使用訂單號orderno做為去重表的唯一索引,每次請求都根據訂單號向去重表中插入一條資料。第一次請求查詢訂單支付狀態,當然訂單沒有支付,進行支付操作,無論成功與否,執行完後更新訂單狀態為成功或失敗,刪除去重表中的資料。後續的訂單因為表中唯一索引而插入失敗,則返回操作失敗,直到第一次的請求完成(成功或失敗)。可以看出防重表作用是加鎖的功能。

這裡使用的防重表可以使用分布式鎖代替,比如redis。訂單發起支付請求,支付系統會去redis快取中查詢是否存在該訂單號的key,如果不存在,則向redis增加key為訂單號。查詢訂單支付已經支付,如果沒有則進行支付,支付完成後刪除該訂單號的key。通過redis做到了分布式鎖,只有這次訂單支付請求完成,下次請求才能進來。相比去重表,將併發做到了快取中,較為高效。思路相同,同一時間只能完成一次支付請求。

這種方式分成兩個階段:申請token階段和支付階段。 第一階段,在進入到提交訂單頁面之前,需要訂單系統根據使用者資訊向支付系統發起一次申請token的請求,支付系統將token儲存到redis快取中,為第二階段支付使用。 第二階段,訂單系統拿著申請到的token發起支付請求,支付系統會檢查redis中是否存在該token,如果存在,表示第一次發起支付請求,刪除快取中token後開始支付邏輯處理;如果快取中不存在,表示非法請求。 實際上這裡的token是乙個信物,支付系統根據token確認操作許可權。缺點是需要系統間互動兩次,流程較上述方法複雜一些。

把訂單的支付請求都快速地接下來,乙個快速接單的緩衝管道。後續使用非同步任務處理管道中的資料,過濾掉重複的待支付訂單。優點是同步轉非同步,高吞吐量。缺點是不能及時地返回支付結果,需要後續監聽支付結果的非同步返回

如何保證介面的冪等性

冪等性是系統服務對外一種承諾,承諾只要呼叫介面成功,外部多次呼叫對系統的影響是一致的。宣告為冪等的服務會認為外部呼叫失敗是常態,並且失敗之後必然會有重試。以sql為例 select col1 from tab1 wher col2 2,無論執行多少次都不會改變狀態,是天然的冪等。update tab...

如果保證介面的冪等性

冪等性原本是數學上的概念,即公式 f x f f x 能夠成立的數學性質 那麼在程式設計領域,為對乙個系統,使用同樣的條件,一次請求和重複的多次請求對系統資源的影響是一致的。冪等性是分布式系統設計中非常重要的概念,具有這一性質的介面在設計時總是秉持這樣的一種理念 呼叫介面發生異常並且重複嘗試時,總是...

如何保證介面的冪等性

冪等性是系統服務對外一種承諾,承諾只要呼叫介面成功,外部多次呼叫對系統的影響是一致的。宣告為冪等的服務會認為外部呼叫失敗是常態,並且失敗之後必然會有重試。介面呼叫下存在的問題 現如今我們的系統大多拆分為分布式soa,或者微服務,一套系統中包含了多個子系統服務,而乙個子系統服務往往會去呼叫另乙個服務,...