面試必問(wèn):接口冪等性
共 2611字,需瀏覽 6分鐘
·
2024-04-17 18:17
一
總體介紹
冪等(Idempotence)是一個(gè)計(jì)算機(jī)領(lǐng)域中的概念,通俗來(lái)講,如果用戶對(duì)一個(gè)操作發(fā)起一次或者多次請(qǐng)求,得到的結(jié)果都是一樣的,那么就認(rèn)為這樣的操作是冪等的。HTTP規(guī)范對(duì)于冪等的說(shuō)明如下:
A request method is considered idempotent if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.
冪等性主要是指重復(fù)請(qǐng)求的場(chǎng)景,比如:
-
用戶多次點(diǎn)擊提交按鈕 由于網(wǎng)絡(luò)原因觸發(fā)了重試機(jī)制
頁(yè)面回退后再次提交
消息重復(fù)消費(fèi)
簡(jiǎn)單來(lái)講,接口最終都是對(duì)于數(shù)據(jù)的操作,也就是數(shù)據(jù)庫(kù)的增刪改查(CRUD),我們來(lái)分析一下,在發(fā)起多次相同的請(qǐng)求時(shí),這些操作的冪等性:
二
冪等性的解決方案
根據(jù)業(yè)務(wù)場(chǎng)景,在數(shù)據(jù)庫(kù)表中添加唯一索引,這樣的話,如果向數(shù)據(jù)庫(kù)中插入已經(jīng)存在的業(yè)務(wù)數(shù)據(jù),系統(tǒng)就會(huì)拋出異常,避免了重復(fù)數(shù)據(jù)的插入。
比如一個(gè)訂單系統(tǒng),把訂單號(hào)作為唯一索引,前端提交訂單之前,請(qǐng)求發(fā)號(hào)器生成一個(gè)訂單號(hào),然后把訂單號(hào)加入到請(qǐng)求頭中,后端程序保存訂單信息到數(shù)據(jù)庫(kù)中,如果拋出異常,數(shù)據(jù)不會(huì)重復(fù)插入,但可以向用戶返回下單成功的提示:
當(dāng)然,這種方式完全依賴數(shù)據(jù)庫(kù)的唯一索引特性,雖然很安全,很好地避免了數(shù)據(jù)重復(fù)問(wèn)題,但把問(wèn)題全部拋給了數(shù)據(jù)庫(kù)層面,會(huì)導(dǎo)致性能問(wèn)題,同時(shí),即使是數(shù)據(jù)重復(fù)了,也提示下單成功,對(duì)于用戶不太友好。
下面我們以一個(gè)實(shí)例來(lái)演示一下這種做法,假如訂單表中的數(shù)據(jù)如下:
UPDATE orders SET amount=102,version=version+1 WHERE order_id=1003 AND version=5
在上面的更新語(yǔ)句中,WHERE條件把version=5也加上了,如果這個(gè)更新操作有重復(fù)請(qǐng)求,那么最終也只有一條sql能夠真正更新數(shù)據(jù),因?yàn)槠渲幸粭lsql更新成功后,version就等于6了,其他的sql就沒(méi)有滿足條件的數(shù)據(jù)了。
使用redis+token的機(jī)制來(lái)保證冪等性是非常常見的一種手段,需要前后端配合一起來(lái)實(shí)現(xiàn),前端首先向后端請(qǐng)求一個(gè)token,后續(xù)的請(qǐng)求中再帶上這個(gè)token,接下來(lái)服務(wù)器再判斷redis中是否存在這個(gè)token,如果存在,則進(jìn)行后續(xù)的業(yè)務(wù)操作,否則說(shuō)明此請(qǐng)求為重復(fù)請(qǐng)求。
在高并發(fā)的場(chǎng)景下,有一個(gè)問(wèn)題需要考慮,是在業(yè)務(wù)操作前刪除token,還是在業(yè)務(wù)操作結(jié)束之后再刪除token?
如果是在業(yè)務(wù)操作前刪除token,如果業(yè)務(wù)操作執(zhí)行失敗了,但還沒(méi)有向客戶端返回處理結(jié)果,此時(shí)客戶端又進(jìn)行了重試,但此時(shí)token已經(jīng)刪除,那么重試的請(qǐng)求就不再進(jìn)行業(yè)務(wù)操作了(比如生成訂單這樣的操作)。
如果先進(jìn)行業(yè)務(wù)操作,再刪除token呢?也會(huì)有問(wèn)題,比如第一次的業(yè)務(wù)操作還沒(méi)有結(jié)束,第二次請(qǐng)求又過(guò)來(lái)了,這時(shí)token還存在,所以第二次請(qǐng)求也會(huì)繼續(xù)執(zhí)行,顯然這是不合理的。
一般情況下,可以采用先刪除token的方式,因?yàn)檫@種方式的結(jié)果是沒(méi)有進(jìn)行業(yè)務(wù)操作,后續(xù)再重新獲取token進(jìn)行操作即可,相對(duì)而言要更合理一些。
三三
總結(jié)
接口冪等性是并發(fā)編程中非常重要的概念,也是各個(gè)公司面試中常問(wèn)的一個(gè)問(wèn)題,本文總結(jié)了常見的實(shí)現(xiàn)冪等性的幾種方案,相對(duì)來(lái)講,使用redis+token的方式是一種比較常見且有效的方式,可以滿足很多場(chǎng)景的需求。
當(dāng)然,也還有其它的些手段來(lái)實(shí)現(xiàn)這樣的功能,包括創(chuàng)建去重表、狀態(tài)機(jī)等,都是在應(yīng)用層面或者數(shù)據(jù)庫(kù)層面來(lái)實(shí)現(xiàn),此處不再展開。
創(chuàng)作不易,煩請(qǐng)點(diǎn)贊分享,感謝!
推薦閱讀:
十多年經(jīng)驗(yàn)的老碼農(nóng),竟然倒在了這個(gè)問(wèn)題上:MySQL中的or是否走索引
