前言
今年年初遇到項目災(zāi)難,解決了不少問題,這是其中一個問題。很早的時候?qū)懙?,學(xué)以致用的。今天看到還有這樣一篇稿文,那就整理下分享給大家學(xué)習(xí)!編程思想之冪等性
什么是冪等性
既然冪等性源于數(shù)學(xué),那我就使用數(shù)學(xué)公式來表示,即可一目了然!
f(f(x)) = f(x)
顯然,從上面的二元函數(shù)可以看出,無論x(等冪元素)被函數(shù)y無限地執(zhí)行運算,它的結(jié)果都是相同的。在計算機編程領(lǐng)域中,我們可以這么定義冪等性:在調(diào)用某個方法、接口中,我們使用相同的參數(shù)(相同的特定參數(shù)),其返回值都是相同的,我們便可稱方法、接口具有冪等性。從信仰上說,冪等性是一種承諾,只要一次答應(yīng)某個承諾,其承諾內(nèi)容都是不會改變的。
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.
如何理解冪等性
理解性的理論,舉例子掌握最快。
- 無心舉例,看場景更易理解。哈哈
冪等性場景設(shè)計
下單處理
這個例子曾經(jīng)出現(xiàn)在我的身邊:微信服務(wù)端在搞事情!
客戶端提交數(shù)據(jù)超過十秒后,他會定時在十秒后自行斷開并自動再次發(fā)起請求,請求的數(shù)據(jù)體一模一樣,但是這樣的請求是不合法的,屬重復(fù)請求。如何解決此事呢?可以使用冪等性作為一個良好的解決方案。為解決此問題,在此先謝謝騰訊大佬CC,后會無期!
原本的方法是這樣設(shè)計的
function add($userToken, $orderMessage){
//todo
}
這樣處理那就不能規(guī)避重復(fù)請求了。
基于冪等性來解決此問題,改進的設(shè)計方法
function add($seq,$userToken, $orderMessage){
// 現(xiàn)根據(jù)seq來判斷是否已經(jīng)處理過了,是的話就返回第一次處理的結(jié)果
$resultJson = $this->redis->get('***_pre_' . $seq);
if(false != $resultJson){
return $resultJson;
}
// 既然沒有處理過,那就正式處理
// todo
// 處理完了,沒有問題那就將結(jié)果保存起來
// todo
return $resultJson;
}
冪等性屬于解決此問題的一部分,是解決方案的一部分,還有另一部分是異步。
提現(xiàn)
基于冪等性設(shè)計 | 防止用戶多次點擊(后端是不相信前端處理的)或者突然網(wǎng)絡(luò)異常等情況下,可以保持數(shù)據(jù)的一致性。
兩個步驟:
- 后端生產(chǎn)票據(jù) | 生產(chǎn)隊時給你發(fā)糧票,你才有機會拿錢去購買柴米油鹽醬醋茶
- 根據(jù)上一步拿到合法的票據(jù)來提現(xiàn)
function createTicketSequence($user) : string{
// todo
}
function withdraw($ticketSequence,$user,$amount){
// todo
}
場景理解
1、用戶在取款的時候,客戶端先帶上token請求服務(wù)端生成一個合法的取款憑證ticketSequeuence
2、用戶在輸入取款金額并確認取款后,客戶端將會帶上用戶登錄憑證userToken、取款票據(jù)ticketSequence以及取款金額amount進行請求
3、服務(wù)端接收到請求后,先校驗userToken,校驗失敗則返回重新登錄,否則換取user對象
4、用戶鑒權(quán)通過后,那么再來校驗取款票據(jù)ticketSequence,票據(jù)不合法,那么取款失敗,否則繼續(xù)進行取款,一直到取款成功并根據(jù)票據(jù)作為冪等值來保存提現(xiàn)成功的結(jié)果
5、即使客戶端請求后與服務(wù)端失去了聯(lián)系,并且服務(wù)端處理成功,客戶端處于假死的狀態(tài)并再次請求取款,也是返回第一次的結(jié)果,并且是迅速的響應(yīng)。