【坑】介面等冪性實施策略
專案剛開始的時候,只關注於功能行開發,但是當功能開發完畢的時候,就會暴露很多問題出來,比如今天要講的介面等冪性。今天會針對實際的應用場景和大家詳情的介紹一下,介面是如何實現等冪性。
場景應用
- 積分兌換(呼叫第三方介面)
- 供應商入駐(表單重複提交)
- 供應商結算申請/運營平臺結算稽核(表單重複提交)
- 線下門店同步訂單流水(對外介面)
- 多個使用者同時註冊同一個手機號(併發操作)
- 使用者申請退款、運營平臺稽核退款(併發操作)
需要做介面等冪性的地方有太多了,我就以上面的應用場景和大傢俱體介紹一下他們各自的解決方案。
積分兌換:
我們先來說一下第一種情況(積分兌換),A系統(也就是我們系統)呼叫B系統進行積分兌換,這個過程可能傳送表單重複提交和併發問題,大家可能會疑問是如何發生的呢?
錯誤場景:
同時多次點選積分兌換按鈕,因為B系統(對方系統)沒有做介面等冪性,這就會發生多次兌換的的情況,如果是使用者故意刷單,對方的系統可能會被刷爆,使用者自己本身積分也會被兌換成負數。
解決方法:
我們可以採用redis鎖機制,以這個使用者id作為鎖顆粒,如果是同一個使用者併發請求,就必須排隊等待。通過這種方式,我們就可以解決上述問題了。
供應商入駐:
電商平臺一般都會有供應商入駐流程,需要填寫供應商基礎資訊和證件資訊,填寫完畢之後就是提交稽核了,這個問題就發生在提交稽核上面。
錯誤場景:
不同瀏覽器同時登入,然後都填寫好入駐資料,最後同時點選提交,這個時候如果不做校驗,後臺就會有兩條一模一樣的入駐資料。
解決方法:
像這種表單重複提交有很多種解決方法,下面我就和大家一一說一下。
一、我們可以用悲觀鎖來實現,但是悲觀鎖效率太低,雖然可以解決表單重複提交問題,但是會嚴重影響效能。
二、悲觀鎖使用的時候會將查詢也一起鎖了,所以這邊相對於悲觀鎖,用樂觀鎖更好,查詢不做限制,修改的時候做限制就可以了。
三、如果是單點服務的話,我們就可以採用同步鎖(synchronized)來實現這個機制,用同步鎖的時候一定要注意鎖的顆粒,如果顆粒太大,那就是一種災難了。
四、下一種就是分散式鎖了,這邊我們可以用redis鎖來實現,例如上面所說的供應商入駐表單重複提交,就可以採用redis鎖實現,可以用供應商賬號來作為鎖的顆粒,這樣其它使用者入駐就完全不會有任何影響。
五、非併發情況下,我們就可以採用先select查詢是否存在這個賬號,存在返回已經提交成功,如果不存在就插入資料。
六、通過前後端token校驗來校驗是否是重複提交,例如前端每次進入的時候都獲取到一個token值,後端會將這個token儲存在redis中,然後提交的時候一起將token傳過去,檢驗如果是同一個token就可以插入資料庫,如果不是同一個就返回失敗。
七、我們可以通過一個狀態機冪來做表單校驗,如果表單已經提交通過,這個時候狀態會發生改變,下次重複提交的時候發現狀態已經修改過了,就會直接返回提交失敗。
八、我們可以利用唯一索引來防止表單重複提交,這種主要是通過資料庫本身來校驗是否主鍵衝突,這種方式一般也不推薦,代價太大了而且主鍵現在一般都是自己生成。
供應商結算申請/運營平臺結算稽核:
作為電商系統,肯定會涉及到供應商結算系統,供應商可以申請結算,運營平臺稽核通過之後就會將錢轉到使用者賬號中,然後使用者就可以申請提現到自己銀行卡中。可見這個過程是整個系統的重中之重,任何一點過錯,都有可能照成金額錯誤。
錯誤場景:
供應商多個瀏覽器同時申請同一筆結算稽核,這個時候如果運營平臺沒有做限制,就有可能結算多次,這個時候就意味著平臺多轉賬給供應商。多個運營平臺人員同時稽核同一位供應商的結算申請,如果沒有做任何限制,也就意味著平臺多轉賬給供應商。如果這兩個都沒做限制。。。那也就意味著平臺破產了。
解決方法:
這邊我們同樣可以採用redis鎖機制,以這個供應商id作為鎖顆粒,同一個供應商的請求就會加鎖,按照順序執行,然後再執行,第一步就會判斷這個供應商是否申請過,通過這種方式就可以解決供應商多次結算申請的問題了。運營平臺多次稽核也可以採用redis鎖來實現,我們這邊以結算申請id作為鎖單位,這樣同一筆結算申請就必須順序執行,然後再執行的第一個進行是否稽核過的查詢就ok了。
線下門店同步訂單流水:
我們電商平臺有對應的線下門店,每次交易之後,線下門店都會同步流水到平臺系統中來。
錯誤場景:
這個時候就會涉及到訂單的漏單和錯單的問題,如果出現這種情況,線下門店肯定會進行補單申請提交。這個時候如果系統平臺不做介面的等冪性,就會有一堆的重複流水訂單產生。
解決方法:
這邊我們同樣可以用redis鎖機制來實現,將流水號作為鎖的最小顆粒,就可以保證不影響高併發的情況下,又可以防止重複資料的產生。
總結:
其實場景都八斤八兩,我們需要選擇最適合當前場景下的方案,來解決對應的問題。下面我們再來總結一下介面等冪性的解決方法:1.資料庫樂觀鎖、2.資料庫悲觀鎖、3.同步鎖(synchronized)、4.分散式鎖(redis鎖)、5.select後update、6.token校驗、7.狀態機冪等、8.唯一索引。上面的場景當然不僅僅是可以用redis鎖來實現,肯定還有其它的,只是我這邊最方便的就是這一種。好了今天的內容就介紹到這邊了,謝謝大家的閱讀~
要更多幹貨、技術猛料的孩子,快點拿起手機掃碼關注我,我在這裡等你哦~