搶微信紅包的時候我們都知道:一個紅包一旦你搶過之后,以后無論你點多少次都是一樣的結(jié)果。紅包會提示你已經(jīng)搶過此紅包,而不會讓你再搶一次。
十載的莘縣網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。成都全網(wǎng)營銷的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整莘縣建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)公司從事“莘縣網(wǎng)站設(shè)計”,“莘縣網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。搶紅包接口就是一個非常典型的冪等接口,搶一次和搶多次具有一樣的效果。類似的接口在我們的開發(fā)過程中會有很多,比如在電商的下單過程中:
訂單創(chuàng)建接口,第一次調(diào)用返回超時了,重試機制一般會再次調(diào)用這個接口,此時我們不能因為這個接口被調(diào)了兩次就創(chuàng)建兩個一樣的訂單;
庫存扣減接口,支付接口也是類似的邏輯;
今天的文章就來講講什么是接口的冪等性,并介紹幾種實現(xiàn)接口冪等性的方案。
冪等原先是數(shù)學(xué)中的一個概念,表示進(jìn)行1次變換和進(jìn)行N次變換產(chǎn)生的效果相同。
當(dāng)我們討論接口的冪等性時一般是在說:
以相同的請求調(diào)用這個接口一次和調(diào)用這個接口多次,對系統(tǒng)產(chǎn)生的影響是相同的。如果一個接口滿足這個特性,那么我們就說這個
接口是一個冪等接口。比如上面的搶紅包接口。
PS:這邊順帶說下冪等和防止重復(fù)提交的區(qū)別。
防止重復(fù)提交更多的是不讓用戶發(fā)起多次一樣的請求。比如說用戶在線購物下單時點了提交訂單按鈕,但是由于網(wǎng)絡(luò)原因響應(yīng)很慢,此時用戶比較心急多次點擊了訂單提交按鈕。
這種情況下就可能會造成多次下單。一般防止重復(fù)提交的方案有:將訂單按鈕置灰,跳轉(zhuǎn)到結(jié)果頁等。主要還是從客戶端的角度來解決這個問題。
冪等更多的是在重復(fù)請求已經(jīng)發(fā)生,或是無法避免的情況下,采取一定的技術(shù)手段讓這些重復(fù)請求不給系統(tǒng)帶來副作用。
并不是所有接口都需要保證冪等性。以相同的請求調(diào)用這個接口一次或多次,需要給調(diào)用方返回一致的結(jié)果時,就要考慮將這個接口設(shè)計成冪等接口。
在我們設(shè)計冪等接口時重點關(guān)注新增接口和更新接口。因為查詢和刪除操作天生是冪等的(根據(jù)id查詢和根據(jù)id刪除多次對系統(tǒng)的影響是一致的),不需要我們提供額外的
技術(shù)手段來保證冪等性。(??)
對于新增和更新接口,大致有以下幾種方案可以保證接口冪等性。
這是一種比較好理解,通用的方案。
當(dāng)調(diào)用接口時,參數(shù)中必須傳入
source
字段和
seq
字段(這邊舉了一個我們項目中的列子,其實并不一定要傳兩個字段,傳一個唯一的序列號uuid也能達(dá)到一樣的效果)。服務(wù)端接收到請求,先判斷自己是否是一個冪等接口,如果不是冪等接口就正常處理請求。
如果是一個冪等接口,就將
source
和
seq
組成聯(lián)合主鍵去數(shù)據(jù)庫表中或者是Redis中查詢,如果沒有查詢到,說明沒處理過這個請求,然后正常處理請求就行了。處理完之后將處理結(jié)果和
source
和
seq
信息一個存入數(shù)據(jù)庫或Redis中。
如果根據(jù)
source
和
seq
能查詢到,說明已經(jīng)處理過這個請求了,直接將處理的結(jié)果返回即可。
我們發(fā)現(xiàn)這種方案非常簡單,而且易于理解,通用。但是如果請求量很大的話,存放請求記錄的表會很大,這個時候可以將一段時間之前的記錄刪除,以提升性能。
這種方案適合用于執(zhí)行新增操作的接口。
比如說新增用戶接口。我們將用戶表中的身份證字段加上唯一索引。當(dāng)同一個請求調(diào)用兩次時,我們可以先根據(jù)身份證字段查詢下用戶是否存在,不存在的話再新增。存在的話就返回新增失敗。
或者直接新增也行,數(shù)據(jù)庫會拋異常,我們對異常處理返回前臺就行了。
PS:大家可能會有一個疑問,我同一個請求調(diào)用兩次,第一返回新增成功,第二次返回失敗,返回的結(jié)果不同啊。這個接口還是冪等接口么?
這邊我要重申下概念,冪等強調(diào)的是接口一次調(diào)用和多次調(diào)用產(chǎn)生的效果是一樣的。這邊調(diào)用一次和調(diào)用多次都是新增了一個對象,所以還是滿足冪等的。
這種方案適用于執(zhí)行更新操作的接口。
樂觀鎖只是在更新數(shù)據(jù)那一刻鎖表,其他時間不鎖表,所以相對于悲觀鎖,效率更高。 我們一般通過數(shù)據(jù)庫來實現(xiàn)樂觀鎖,比較通用的做法是增加一個時間戳字段。
Copyupdate table_xxx set name=#name#, timestamp = now where id=#id# and timestamp=#timestamp# --這個值由前端到數(shù)據(jù)中查詢出來,再傳過來