最近很多人都在談論幂等性,好吧,這回我也來聊聊這個話題,光看着倆字,一開始的确有點一頭霧水,國文不好嘛,詞太專業嘛,對吧
現如今我們的系統大多拆分為分布式SOA,或者微服務,一套系統中包含了多個子系統服務,而一個子系統服務往往會去調用另一個服務,而服務調用服務無非就是使用RPC通信或者restful,既然是通信,那麼就有可能再伺服器處理完畢後傳回結果的時候挂掉,這個時候使用者端發現很久沒有反應,那麼就會多次點選按鈕,這樣請求有多次,那麼處理資料的結果是否要統一呢?那是肯定的!尤其再支付場景。
幂等性:就是使用者對于同一操作發起的一次請求或者多次請求的結果是一緻的,不會因為多次點選而産生了副作用。舉個最簡單的例子,那就是支付,使用者購買商品使用約支付,支付扣款成功,但是傳回結果的時候網絡異常,此時錢已經扣了,使用者再次點選按鈕,此時會進行第二次扣款,傳回結果成功,使用者查詢餘額返發現多扣錢了,流水記錄也變成了兩條...
在以前的單應用系統中,我們隻需要把資料操作放入事務中即可,發生錯誤立即復原,但是再響應用戶端的時候也有可能出現網絡中斷或者異常等等。
在增删改查4個操作中,尤為注意就是增加或者修改,
查詢對于結果是不會有改變的,
删除隻會進行一次,使用者多次點選産生的結果一樣
修改在大多場景下結果一樣
增加在重複送出的場景下會出現
那麼如何設計接口才能做到幂等呢?
方法一、單次支付請求,也就是直接支付了,不需要額外的資料庫操作了,這個時候發起異步請求建立一個唯一的ticketId,就是門票,這張門票隻能使用一次就廢棄,具體步驟如下:
異步請求擷取門票
調用支付,傳入門票
根據門票ID查詢此次操作是否存在,如果存在則表示該操作已經執行過,直接傳回結果;如果不存在,支付扣款,儲存結果
傳回結果到用戶端
如果步驟4通信失敗,使用者再次發起請求,那麼最終結果還是一樣的
方法二、分布式環境下各個服務互相調用
這邊就要舉例我們的系統了,我們支付的時候先要扣款,然後更新訂單,這個地方就涉及到了訂單服務以及支付服務了。
使用者調用支付,扣款成功後,更新對應訂單狀态,然後再儲存流水。
而在這個地方就沒必要使用門票ticketId了,因為會比較閑的麻煩
(支付狀态:未支付,已支付)
步驟:
1、查詢訂單支付狀态
2、如果已經支付,直接傳回結果
3、如果未支付,則支付扣款并且儲存流水
4、傳回支付結果
對于做過支付的朋友,幂等,也可以稱之為沖正,保證用戶端與服務端的交易一緻性,避免多次扣款。
最後來看一下我們的訂單流程,雖然不是很複雜,但是最後在支付環境是一定要實作幂等性的
