重復(fù)下單
案例1:
1. 用戶點(diǎn)擊“確認(rèn)下單”按鍵進(jìn)行下單操作;
2. 后臺(tái)系統(tǒng)接收到請(qǐng)求,并處理返回結(jié)果;
3. 網(wǎng)絡(luò)發(fā)生問(wèn)題,用戶沒(méi)有收到成功返回,以為沒(méi)有下單成功,再次發(fā)起請(qǐng)求;
案例2:
1. 用戶因?yàn)槟撤N原因,多次發(fā)起“確認(rèn)下單”請(qǐng)求,但以為只請(qǐng)求一次;
2. 后臺(tái)系統(tǒng)在1秒內(nèi)接收到同一個(gè)用戶的多次相同請(qǐng)求,并處理返回結(jié)果;
HTTP的冪等性
HTTP方法的冪等性是指一次和多次請(qǐng)求某一個(gè)資源應(yīng)該具有同樣的結(jié)果。在HTTP 1.1規(guī)范中冪等性定義是:
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ù)學(xué)表達(dá):f(f(x)) = f(x)。
冪等性的系統(tǒng)說(shuō)明
冪等性是系統(tǒng)的接口對(duì)外一種承諾而不是實(shí)現(xiàn), 承諾只要調(diào)用接口成功, 外部多次調(diào)用對(duì)系統(tǒng)的影響是一致的. 聲明為冪等的接口會(huì)認(rèn)為外部調(diào)用失敗是常態(tài), 并且失敗之后必然會(huì)有重試。
檢測(cè)重復(fù)下單
在下單接口中,使用隨機(jī)字符串來(lái)生成一個(gè)處理訂單Id來(lái)標(biāo)識(shí)一個(gè)訂單接口傳入(由后端系統(tǒng)來(lái)生成);后臺(tái)系統(tǒng)保證每個(gè)訂單傳入的都必須是唯一,如果后臺(tái)系統(tǒng)發(fā)現(xiàn)處理訂單Id重復(fù)就拒絕成生訂單
接口的冪待性
接單接口中傳入的ID,至多只會(huì)被處理一次(處理完的,直接刪除傳入的ID),且每次調(diào)用都返回第一次調(diào)用時(shí)的處理結(jié)果。這樣調(diào)用方就可以放心的多次調(diào)用,而不會(huì)造成系統(tǒng)數(shù)據(jù)混亂與結(jié)果的錯(cuò)亂。
鑒于這個(gè)機(jī)制,案例1與2的解決方案如下:
- 每次進(jìn)入下單場(chǎng)景,都需要獲取一個(gè)全新的Id
- 用戶一旦點(diǎn)擊“確認(rèn)下單”按鍵進(jìn)行下單操作,此按建都要立刻Hold住,設(shè)置為“不可用狀態(tài)”,等待后端接口返回;
- 如果超過(guò)一定的時(shí)限(1-2秒)沒(méi)有收到后端系統(tǒng)的返回,則進(jìn)入到另一個(gè)頁(yè)面彈出相應(yīng)的提示告之用戶下單異常請(qǐng)查詢或訂單無(wú)法確定,引導(dǎo)用戶去查詢訂單狀態(tài),反復(fù)確認(rèn)直到訂單狀態(tài)是成功或失敗。
- 如果反復(fù)確認(rèn)都不無(wú)法得后端返回的響應(yīng),請(qǐng)?jiān)谙鄳?yīng)的界面上引導(dǎo)人戶去重新下單。
- 后臺(tái)在接單接口上要符合冪等性。