冪等性學習前端
一:什麼是冪等性java
在這裏須要有如下幾個問題須要注意:sql
1:冪等性的實質是一次或屢次請求同一個資源,其結果是相同的。其關注的是對資源產生的影響(反作用)而不是結果,結果能夠不一樣。好比列表查詢的時候,一邊在save或者是update,而你這邊仍是在select,其結果確定是不一樣的,可是你的select操做並未對數據(資源)產生影響(反作用);數據庫
2:冪等性不只僅只是一次或者屢次請求的時候對資源沒有反作用。好比根據id對數據庫的查詢操做,此操做對數據庫沒有增刪改,因此屢次查詢操做對數據庫結果是沒有任何影響的;網絡
3:冪等性還包括了第一次請求資源的時候,對資源產生了反作用,可是在之後屢次一樣的請求操做的時候,都不會在對資源產生反作用了。好比咱們根據id更新訂單狀態從支付中變爲支付完成這個操做,在執行第一次的時候,會更新爲支付完成。以後在根據這個id執行此操做,不管執行多少次其結果和第一次執行後的結果同樣;併發
4:冪等性關注的是之後的屢次請求是否對資源產生了反作用,而不是關注的結果;ide
5:須要說明的是網絡超時、服務宕機等問題,不是冪等的範圍。學習
冪等性是系統服務對外的一種承諾(注意,是一種承諾,而不是一種實現),接口服務提供方承諾只要調用接口成功了,外部屢次調用對系統的影響是一致的。這裏須要強調一點就是,聲明爲冪等的服務會認爲調用方調用失敗是常態,是正常業務,而且容許在調用失敗後必然會有重試的。spa
來源:凱哥Java(kaigejava)設計
二:什麼狀況下須要使用冪等
在咱們開發中,常常會遇到一個頭疼的事情—重複提交的狀況。重複提交狀況有多種緣由產生的。如因爲網絡問題沒法收到請求結果狀況下而從新發起的請求或者是由於調用方前端操做抖動而形成的重複提交。
重複提交操做帶來的嚴重後果在交易系統、支付系統中因重複提交而產生的問題尤爲的明顯。如:咱們發起支付的時候向支付寶支付請求,不管是交易系統自身bug仍是交易系統與支付寶之間的網絡問題致使重複發送,支付寶應該而且必須只能扣用戶一次錢的。在這種需求下的系統在設計的時候,咱們就須要將系統或者服務設計成冪等的。
三:冪等和防重複提交比較
重複提交:重複提交是在第一次請求成功的狀況下,人爲的進行屢次操做,從而致使不知足冪等性要求的服務屢次改變數據狀態。
冪等:更多使用的狀況是第一次請求知道結果(好比常見的網絡抖動致使鏈接超時)或者失敗異常狀況下,發起屢次請求的,其目的是屢次確認第一次請求成功,卻不會由於屢次請求而出現屢次的狀態變化。
什麼狀況下須要保障冪等性?
在這裏,咱們以sql爲例來說解。在下面三種場景中,只要第三種場景須要開發人員使用其餘策略來保障冪等性:
1:查詢狀況
Select * from table where id = 2
不管執行多少次都不會對資源形成反作用,因此能夠說是自然的冪等
2:根據id更新
Update table set status =1 where id =2
不管執行成功多少次狀態都是一致的,第一次執行成功對資源形成的反作用和屢次執行成功對數據形成的反作用是同樣的。所以能夠說這種場景也是冪等操做
3:不是冪等狀況
Update table set version = version+1 where id = 2
每次執行的結果都會發生變化,也就是說對資源形成了反作用,這種不是冪等的。這種狀況若是想要保證冪等,語句能夠這麼寫:update table set version = version+1 where id = 2 and version = 1.這樣就能夠保證冪等了。
爲何要設計冪等性的服務?
冪等性的服務可使得客戶端的處理業務邏輯變的簡單了,可是確實以犧牲服務端邏輯變複雜爲代價的。由於在知足冪等服務的需求下邏輯至少須要包含如下兩點:
1:首選去查詢上一次的執行狀態(結果),若是沒有則認爲是第一次請求。這樣就增長了業務難度
2:在服務改變狀態的業務邏輯前,保證防重複提交的邏輯
冪等的不足:
經過上面咱們知道了冪等服務是以犧牲服務提供者邏輯和成本爲代價的。因此,是否有必要,須要根據具體場景具體來分析的。所以除了業務上的特殊要求外,儘可能不要提供冪等的接口。
1:增長了額外的控制冪等的業務邏輯,複雜了業務功能;
2:把並行執行的功能改成串行執行,這樣就下降了執行的效率。
保證冪等策略
其實在保證冪等的業務會經過惟一的業務單號來保證的。也就是說相同的單號,被認爲是同一筆業務。使用惟一的業務單號來確保,後面屢次相同的業務單號的的處理邏輯和執行兄啊過是一致的。咱們以常見的支付爲例(在不考慮併發狀況下),實現冪等很簡單:
1:先查詢一下訂單是否已經支付過
2:若是已經支付過,則返回支付成功;若是沒有支付,在進行支付流程操做後,將訂單狀態修改成已支付。