聊聊冪等

什么是冪等(idempotency)?簡單一點說,一個操作如果具有任意多次執(zhí)行所產(chǎn)生的影響與一次執(zhí)行產(chǎn)生的影響相同,就是冪等。

這樣來說,似乎也很容易理解。但是要知道,這樣的定義,其實是一個語義范疇內(nèi)對行為結(jié)果的定義。如果用語法和規(guī)則去確保行為能達到這個結(jié)果,往往需要很謹慎的設(shè)計與實現(xiàn)。在系統(tǒng)中,冪等是一個很重要的概念。無論是在大型的互聯(lián)網(wǎng)系統(tǒng)還是企業(yè)級應(yīng)用,REST API都被廣泛使用。而正確的使用冪等,是API技術(shù)中極其重要的一個技術(shù)點。

為什么說非常重要?日常生活中,支付是最常見的交易場景。比如我們在給支付寶發(fā)送一筆付款請求時,正常情況下,用戶扣款成功,支付寶返回支付成功的信息。但是如果發(fā)生異常怎么辦?比如客戶端發(fā)出請求后,請求超時,你沒有收到下游系統(tǒng)的處理結(jié)果,那到底是成功還是失敗,或者其它情況。

請求超時的情況也分很多種:

1、這個請求到達支付寶前端之前就發(fā)生了超時,也就是支付寶根本就不知道有這筆訂單的存在,也就是通常說的漏單。

2、支付寶已經(jīng)收到了這個請求,但是支付失敗,這時發(fā)生超時異常,支付寶處理失敗。

3、支付寶收到了這個請求,并且支付也成功,但這時候還是發(fā)生了超時,支付寶處理成功,但時沒有回執(zhí)。

4、支付寶收到了這個請求,支付也成功,并且發(fā)送了回執(zhí),但因為網(wǎng)絡(luò)但原因客戶端沒有收到,客戶端超時,所以并不知道處理結(jié)果。

遇到這種情況怎么辦?常見但做法是重試機制,重試機制有幾種方案,這里不展開。但是有一個存在的問題,請求超時是上面的那一種,會不會造成重復交易的問題?這就涉及到冪等性問題。

那么冪等又該如何實現(xiàn)呢?多次執(zhí)行所產(chǎn)生的影響和一次執(zhí)行產(chǎn)生的影響相同。簡而言之,我們需要一個去重的機制,這往往有很多實現(xiàn)方法,但有兩個很關(guān)鍵的因素:

1、冪等令牌。也就是說客戶端和服務(wù)端通過什么來識別是同一個請求,或者是一個請求嘗試多次。這一般需要客戶端和服務(wù)端協(xié)議,通常由客戶端來產(chǎn)生令牌。

2、確保唯一性。服務(wù)端通過什么來確認是同一個請求,也就是說怎么確認請求的唯一性,這通常使用數(shù)據(jù)庫來實現(xiàn)。把冪等令牌作為數(shù)據(jù)庫列的唯一索引。但當有兩個同樣的冪等令牌到達時,必然有一個會失敗。注意一點,簡單的讀檢查并不一定行,因為讀與讀之間存在競爭條件,因此有可能出錯。

如果一個系統(tǒng)能正確的處理上面兩個要素,那基本上就能達到冪等等要求。那么現(xiàn)實系統(tǒng)中,常見等問題都出現(xiàn)在哪里呢?

1、冪等令牌什么時候產(chǎn)生,怎么產(chǎn)生?這一點很重要。還是拿上面等例子來說,支付寶能確定對每一筆支付請求只執(zhí)行一次,那它必然有一個唯一標識來區(qū)分。假如客戶端對同一筆對多次請求,每次請求的冪等令牌都不一樣,那支付寶也確認不了這是同一筆交易。

2、令牌有沒有可能被誤刪的可能。這是上面的一種特殊情況。冪等令牌是由客戶端生成的,那么如果客戶端在使用完令牌后,不小心因為DB rollback等原因被刪除啦。這時客戶端就不知道之前已經(jīng)發(fā)送過一次交易。這時候就有可能產(chǎn)生一筆新的交易,并產(chǎn)生一筆新的訂單,服務(wù)端對此時毫無感知。所以這個必須客戶端來保證。

3、各種競爭條件。上面說的用DB讀來確保唯一性經(jīng)常因為競爭不工作。其實一個實現(xiàn)冪等等系統(tǒng)中,各個環(huán)節(jié)都需要配合實現(xiàn),都需要考慮競爭條件。

4、對服務(wù)對重試處理,一般都是服務(wù)端實現(xiàn)的。一個常見的做法是要區(qū)分正在處理中,處理成功,處理失敗。這樣當客戶端重新請求時,根據(jù)具體情況是直接返回還是再次處理。

5、一個系統(tǒng)中有多個冪等。一個是說服務(wù)端不是由一個系統(tǒng)實現(xiàn)的,A系統(tǒng)發(fā)給B系統(tǒng),B系統(tǒng)再發(fā)給C系統(tǒng),C處理完了可能還需要發(fā)給D系統(tǒng),之后再D返回C,C返回B,B再返回A等等各種情況。那么在整個鏈路中,如果A、B、C、D中有一個系統(tǒng)沒有正確的實現(xiàn)冪等,也還是會出現(xiàn)冪等漏洞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,540評論 19 139
  • API定義規(guī)范 本規(guī)范設(shè)計基于如下使用場景: 請求頻率不是非常高:如果產(chǎn)品的使用周期內(nèi)請求頻率非常高,建議使用雙通...
    有涯逐無涯閱讀 2,922評論 0 6
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,940評論 25 709
  • 參與者 條款和條件 請仔細閱讀這些條款。如果您不同意這些條款,請勿購買項目土地。 您在Brainbot Labs建...
    悅續(xù)閱讀 750評論 0 0
  • form表單有什么作用?有哪些常用的input 標簽,分別有什么作用? 概述 作用 HTML 元素 表示了文檔...
    vs陳默閱讀 501評論 0 0

友情鏈接更多精彩內(nèi)容