什麼是冪等性?

如果要追根溯源,冪等性是數學中的一個概念,表達的是N次變換與1次變換的結果相同。那麼在我們的微服務,分散式系統中的冪等性指的就是用戶對於同一操作發起的一次請求或者多次請求的結果是一致的,不會因為多次點擊而產生了錯誤的結果。就直觀的列子就是支付的時候,點擊支付時,因為網路或其他原因導致異常,但是錢已經扣掉了,還沒來得及返回給用戶,此時用戶又點擊了支付,此時發生了二次扣費。

我們同樣也可以將這個對數據的操作放入到事務中來,但是響應給客戶端的時候依然可能發生異常或者報錯。

常見的應用場景:面試的時候 問:A賬戶轉賬100元到B賬戶,這中間發生了什麼?(這裡應該圍繞著冪等性來作答)

業務場景:

  • 一個訂單創建介面,第一次調用超時了,然後調用方重試了一次
  • 在訂單創建時,我們需要去扣減庫存,這時介面發生了超時,調用方重試了一次
  • 當這筆訂單開始支付,在支付請求發出之後,在服務端發生了扣錢操作,介面響應超時了,調用方重試了一次
  • 一個訂單狀態更新介面,調用方連續發送了兩個消息,一個是已創建,一個是已付款。但是你先接收到已付款,然後又接收到了已創建
  • 在支付完成訂單之後,需要發送一條簡訊,當一臺機器接收到簡訊發送的消息之後,處理較慢。消息中間件又把消息投遞給另外一臺機器處理

那麼我們要如何設計介面來達到冪等性呢?

方法一:全局唯一ID

如果使用全局唯一ID,就是根據業務的操作和內容生成一個全局ID,在執行操作前先判斷這個全局唯一ID是否存在,如果不存在則把全局ID,存儲到存儲系統中,比如redis資料庫中。如果存在則表示該方法已經執行。

方法二:去重表

這種方法適用於在業務中有唯一標識的插入場景中,比如在以上的支付場景中,如果一個訂單只會支付一次,所以訂單ID可以作為唯一標識。這時,我們就可以建一張去重表,並且把唯一標識作為唯一索引,在我們實現時,把創建支付單據和寫入去去重表,放在一個事務中,如果重複創建,資料庫會拋出唯一約束異常,操作就會回滾。


推薦閱讀:
相關文章