冪等性(Idempotence)。在HTTP/1.1規範中冪等性的定義是:前端
Methods can also have the property of 「idempotence」 in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.數據庫
冪等性:就是用戶對於同一操做發起的一次請求或者屢次請求的結果是一致的,不會由於屢次點擊而產生了反作用。網絡
那麼咱們爲何須要接口具備冪等性呢?設想一下如下情形:併發
在分佈式環境中,網絡環境更加複雜,因前端操做抖動、網絡故障、消息重複、響應速度慢等緣由,對接口的重複調用機率會比集中式環境下更大,尤爲是重複消息在分佈式環境中很難避免。分佈式
接口的冪等性實際上就是接口可重複調用,在調用方屢次調用的狀況下,接口最終獲得的結果是一致的。有些接口能夠自然的實現冪等性,好比查詢接口,對於查詢來講,你查詢一次和兩次,對於系統來講,沒有任何影響,查出的結果也是同樣。ide
除了查詢功能具備自然的冪等性以外,增長、更新、刪除都要保證冪等性。那麼如何來保證冪等性呢?高併發
冪等須要經過惟一的業務單號來保證。也就是說相同的業務單號,認爲是同一筆業務。使用這個惟一的業務單號來確保,後面屢次的相同的業務單號的處理邏輯和執行效果是一致的。
下面以支付爲例,在不考慮併發的狀況下,實現冪等很簡單:①先查詢一下訂單是否已經支付過,②若是已經支付過,則返回支付成功;若是沒有支付,進行支付流程,修改訂單狀態爲‘已支付’。設計
上述的保證冪等方案是分紅兩步的,第②步依賴第①步的查詢結果,沒法保證原子性的。在高併發下就會出現下面的狀況:第二次請求在第一次請求第②步訂單狀態尚未修改成‘已支付狀態’的狀況下到來。既然得出了這個結論,餘下的問題也就變得簡單:把查詢和變動狀態操做加鎖,將並行操做改成串行操做。日誌
一、悲觀鎖,select for update,整個執行過程當中鎖定該訂單對應的記錄。二、樂觀鎖,affectrows = db.update(「update payorder set state=’已支付’ where orderid=$orderid and state=’未支付’ 「),若是affectrows=1,執行充值,不然返回已處理。三、定義防重複表,orderid爲unique key或者primary key,執行前,先insert,若insert成功則執行充值,不然返回已處理