但是在分布式架構里面,因為涉及到遠程通信,它就會涉及到第三種狀態,就是未知狀態,未知狀態可能表示超時、網絡延遲、數據包丟失等等。那么這個數據的未知狀態會導致我們調用端對這個結果是未知的,如果在這個未知的場景下,調用端或客戶端再次重試去發起請求,也許這個請求對於服務端來說收到並且已經處理了,但是客戶端不知道,所以它再次嘗試發送多一次請求,那服務端就會收到兩次請求,如果服務器端不做處理的話就會導致數據做了兩次累加或者兩次更新,這樣就會發生非常大的影響。
比如支付場景:如果用戶對同一個訂單發起兩次支付操作,那么這個時候服務端不去做相應的處理的話,它就會完成兩筆扣款記錄,那么這個地方就會造成用戶的資金損失,這種情況是絕對不允許在互聯網產品上出現的。
還有絕大部分消息中間件都可能存在消息發送多次的情況,那怎么保證在消息多發的情況下(基於broker發送到消費者)的數據安全性,這也是我們必須要解決的場景。
冪等性就是用來解決這樣的場景的,冪等性簡單來說就是用戶對同一個操作發起多次請求以后,對於數據的影響的結果是不變的,一次請求跟N次請求的結果是一樣的。
在這里我簡單地說說兩種方式的解決方案:
1、可以使用數據庫的唯一約束,對某一個關鍵的數據設置一個唯一索引,第二次請求過來的時候它沒有辦法正常入庫,這時會拋出一個重復的異常,服務端可以捕獲到這個異常,然后不作處理;
2、狀態機冪等,狀態機實際上在很多開源中間件、軟件里面都有提到和涉及到。那么什么是狀態機呢?它是一種特殊的組織代碼,它能夠確保你的對象隨時都知道自己所處的狀態以及可以在這個狀態下做出相應的可以做的事情。簡單來說就是對於一個數據會存在一個不同的狀態,而且這個狀態是可變的。下面一個例子:
發起支付的時候這個狀態是支付中,后面有已支付和支付失敗,狀態隨着業務的驅動而變化,那它是怎么實現冪等的呢?
如果請求的是修改操作,那么 update xxxx where status = 1,這就是說只有這個狀態等於1的情況下才能修改,也說明當前的修改操作是因為某一場景才觸發的,比如說原來的等待支付變成支付中,意味着這個支付中的狀態必須是在等待支付的狀態下才能去修改的,它的前置條件就是等待支付,這個就是使用狀態機的方式去實現冪等。