程式設計思想之冪等性 | 程式設計之道

AlicFeng發表於2018-10-23

前言

今年年初遇到專案災難,解決了不少問題,這是其中一個問題。很早的時候寫的,學以致用的。今天看到還有這樣一篇稿文,那就整理下分享給大家學習!程式設計思想之冪等性


什麼是冪等性
既然冪等性源於數學,那我就使用數學公式來表示,即可一目瞭然!

f(f(x)) = f(x)

顯然,從上面的二元函式可以看出,無論x(等冪元素)被函式y無限地執行運算,它的結果都是相同的。在計算機程式設計領域中,我們可以這麼定義冪等性:在呼叫某個方法、介面中,我們使用相同的引數(相同的特定引數),其返回值都是相同的,我們便可稱方法、介面具有冪等性。從信仰上說,冪等性是一種承諾,只要一次答應某個承諾,其承諾內容都是不會改變的。

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.

如何理解冪等性
理解性的理論,舉例子掌握最快。

  • 無心舉例,看場景更易理解。哈哈

冪等性場景設計

下單處理

這個例子曾經出現在我的身邊:微信服務端在搞事情!
客戶端提交資料超過十秒後,他會定時在十秒後自行斷開並自動再次發起請求,請求的資料體一模一樣,但是這樣的請求是不合法的,屬重複請求。如何解決此事呢?可以使用冪等性作為一個良好的解決方案。為解決此問題,在此先謝謝騰訊大佬CC,後會無期!

原本的方法是這樣設計的

function add($userToken, $orderMessage){
  //todo
}

這樣處理那就不能規避重複請求了。

基於冪等性來解決此問題,改進的設計方法

function add($seq,$userToken, $orderMessage){
  // 現根據seq來判斷是否已經處理過了,是的話就返回第一次處理的結果
  $resultJson = $this->redis->get('***_pre_' . $seq);
  if(false != $resultJson){
    return $resultJson;
  }
  // 既然沒有處理過,那就正式處理
  // todo 
  // 處理完了,沒有問題那就將結果儲存起來
  // todo
  return $resultJson;
}

冪等性屬於解決此問題的一部分,是解決方案的一部分,還有另一部分是非同步


提現
基於冪等性設計 | 防止使用者多次點選(後端是不相信前端處理的)或者突然網路異常等情況下,可以保持資料的一致性。

兩個步驟:

  • 後端生產票據 | 生產隊時給你發糧票,你才有機會拿錢去購買柴米油鹽醬醋茶
  • 根據上一步拿到合法的票據來提現
function createTicketSequence($user) : string{
  // todo 
}
function withdraw($ticketSequence,$user,$amount){
  // todo
}

場景理解
1、使用者在取款的時候,客戶端先帶上token請求服務端生成一個合法的取款憑證ticketSequeuence
2、使用者在輸入取款金額並確認取款後,客戶端將會帶上使用者登入憑證userToken、取款票據ticketSequence以及取款金額amount進行請求
3、服務端接收到請求後,先校驗userToken,校驗失敗則返回重新登入,否則換取user物件
4、使用者鑑權通過後,那麼再來校驗取款票據ticketSequence,票據不合法,那麼取款失敗,否則繼續進行取款,一直到取款成功並根據票據作為冪等值來儲存提現成功的結果
5、即使客戶端請求後與服務端失去了聯絡,並且服務端處理成功,客戶端處於假死的狀態並再次請求取款,也是返回第一次的結果,並且是迅速的響應。

價值源於技術,技術源於分享!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

價值源於技術,貢獻源於分享 | 筆記分享歸檔
No matter where I am, I will reply you immediately when I see the email.
My Email: echo "YUBzYW1lZ28uY29tCg==" | base64 -d
個人比較喜歡分享,若有不對的地方非常感謝指出
相互學習、共同進步~

相關文章