最近不少人都在談論冪等性,好吧,這回我也來聊聊這個話題,光看着倆字,一開始的確有點一頭霧水,語文很差嘛,詞太專業嘛,對吧數據庫
現現在咱們的系統大多拆分爲分佈式SOA,或者微服務,一套系統中包含了多個子系統服務,而一個子系統服務每每會去調用另外一個服務,而服務調用服務無非就是使用RPC通訊或者restful,既然是通訊,那麼就有可能再服務器處理完畢後返回結果的時候掛掉,這個時候用戶端發現好久沒有反應,那麼就會屢次點擊按鈕,這樣請求有屢次,那麼處理數據的結果是否要統一呢?那是確定的!尤爲再支付場景。服務器
冪等性:就是用戶對於同一操做發起的一次請求或者屢次請求的結果是一致的,不會由於屢次點擊而產生了反作用。舉個最簡單的例子,那就是支付,用戶購買商品使用約支付,支付扣款成功,可是返回結果的時候網絡異常,此時錢已經扣了,用戶再次點擊按鈕,此時會進行第二次扣款,返回結果成功,用戶查詢餘額返發現多扣錢了,流水記錄也變成了兩條...restful
在之前的單應用系統中,咱們只須要把數據操做放入事務中便可,發生錯誤當即回滾,可是再響應客戶端的時候也有可能出現網絡中斷或者異常等等。網絡
在增刪改查4個操做中,尤其注意就是增長或者修改,異步
查詢對於結果是不會有改變的,分佈式
刪除只會進行一次,用戶屢次點擊產生的結果同樣微服務
修改在大多場景下結果同樣設計
增長在重複提交的場景下會出現rest
那麼如何設計接口才能作到冪等呢?blog
方法1、單次支付請求,也就是直接支付了,不須要額外的數據庫操做了,這個時候發起異步請求建立一個惟一的ticketId,就是門票,這張門票只能使用一次就做廢,具體步驟以下:
異步請求獲取門票
調用支付,傳入門票
根據門票ID查詢這次操做是否存在,若是存在則表示該操做已經執行過,直接返回結果;若是不存在,支付扣款,保存結果
返回結果到客戶端
若是步驟4通訊失敗,用戶再次發起請求,那麼最終結果仍是同樣的
方法2、分佈式環境下各個服務相互調用
這邊就要舉例咱們的系統了,咱們支付的時候先要扣款,而後更新訂單,這個地方就涉及到了訂單服務以及支付服務了。
用戶調用支付,扣款成功後,更新對應訂單狀態,而後再保存流水。
而在這個地方就不必使用門票ticketId了,由於會比較閒的麻煩
(支付狀態:未支付,已支付)
步驟:
一、查詢訂單支付狀態
二、若是已經支付,直接返回結果
三、若是未支付,則支付扣款而且保存流水
四、返回支付結果
若是步驟4通訊失敗,用戶再次發起請求,那麼最終結果仍是同樣的
對於作過支付的朋友,冪等,也能夠稱之爲衝正,保證客戶端與服務端的交易一致性,避免屢次扣款。
最後來看一下咱們的訂單流程,雖然不是很複雜,可是最後在支付環境是必定要實現冪等性的