引子 群里發(fā)了一個總共1千元的拼手氣紅包,共10個,。靜兒點進去,,額,搶到了0.05元,。這個不甘心啊,。退出來重新打開了這個紅包,,你猜怎樣,?顯示我搶到了0.05元! 這就是冪等(idempotence),,不管多少次請求某一個資源,,對資源都具有相同的影響。冪等性是系統(tǒng)的接口對外一種承諾,,承諾只要調用接口成功,,外部多次調用對系統(tǒng)只產生一次副作用。 為什么要冪等 世界上最遙遠的距離是我終于鼓起勇氣,,對著馬路對面的你大喊:“你愿意娶我嗎,?”我看到你面帶燦爛的笑容,正回答的時候……一輛大卡車駛過,,你的回答我沒有聽見,。 因各種不可抗因素產生的沒有收到響應,一個簡單有效的方法就是重試,。被重試的接口必須是冪等的,。 冪等性是分布式系統(tǒng)設計中的一個重要概念,對超時處理,、系統(tǒng)恢復等具有重要意義,。 保證冪等的手段 保證冪等需要理清楚兩件事情:冪等條件和期望結果,。 大家可能聽說過保證冪等的手段有token令牌、分布式鎖,、去重表,、數據庫唯一索引等。這些所謂的冪等手段實際上防重手段,。防重本質是防止一個相同的請求被當成多個不同的請求來處理,。冪等的條件是知道這是一個相同的請求。防重和冪等本質上是兩個不同的階段,。 狀態(tài)機冪等 在支付場景中,,創(chuàng)建了一個支付訂單,發(fā)起了一個支付請求,,這個訂單不論多少次重復請求,,都應該保證最多只扣款一次。即
為了實現這個目標,,可以考慮使用有限狀態(tài)機,。 有限狀態(tài)機(Finite-state machine FSM),又稱有限狀態(tài)自動機,,簡稱狀態(tài)機,,是表示有限個狀態(tài)以及在這些狀態(tài)之間的轉移和動作等行為的數學模型。用于處理復雜的狀態(tài)轉換,。 在這個支付的例子中,,為了化簡,不考慮退款,、取消訂單等復雜的狀態(tài),,只考慮未支付和已支付兩種狀態(tài)之間的轉換。 由上面的狀態(tài)轉換圖可以看到,,相同支付訂單ID從未支付狀態(tài),,要不就是支付不成功停留在未支付狀態(tài),要不就是支付成功,,狀態(tài)轉移為已支付,。此狀態(tài)轉移過程不可逆。
這是一個java版本的簡單狀態(tài)機實現,。狀態(tài)機里定義了一個未支付狀態(tài)和其行為changeState,。changeState又定義了一個未支付狀態(tài)和其行為changeState。 利用狀態(tài)機來實現這個冪等支付請求的設計流程圖如下: 參考狀態(tài)機實現和上圖可知,,相同支付ID的請求,,支付狀態(tài)只能進行一次從未支付到已支付的轉換。從而保證了其冪等性。 按目標冪等 先來回答一個小學生的問題: 定了一個會議,,參加人數為10人,。發(fā)現會議室的椅子只有5把。3個提前來到會議室的同學熱心的去其他地方搬椅子進來,。問:每人要搬幾把椅子,? 有人要說這不是把簡單的問題復雜了嗎?大家看到椅子不夠就去搬,,看夠10把椅子了就不搬就可以了,。對了,這其實是一個很好的解題思路,,完全可以用在設計當中,,就是按目標冪等。
利用按目標冪等來實現這個總數10把椅子請求的設計流程圖如下: 采用按目標的設計,,相同會議ID,,不管多少次請求,請求椅子的總數就是10把,。多次請求不改變行為,,從而實現了冪等。 總結 支持冪等是一個接口的基本素養(yǎng) |
|