根據實際工作經驗總結一下個人.Net高併發處理做法

場景描述

1.用戶下單,商品庫存已經不足了,但還是扣減了

2.醫生開方,藥品不足了,但還是被開了出去

··· 類似場景

解決思路

思路1:預扣庫存

用戶下單時,系統先進行預扣庫存操作,然後後將“下單業務”發佈到MQ(消息隊列)進行處理,成功通知,失敗回滾預扣庫存操作

  • 對於預扣庫存時可能出現的“超賣”現象,可以採用針對數據庫表的悲觀/樂觀鎖,具體用哪種,看場景,下文有講

思路2:異步通知

用戶下單時,直接提交,後臺丟入MQ,然後進行業務處理,前端直接提示操作完成

  • 這個處理方式,極大的提升吞吐量,因爲不需要“即刻”處理,後續獲取結果方式則可通過各種方式來通知,如微信公衆的消息訂閱模板消息,短信、郵件,等。
  • 這個場景在BAT產品中可以找到相關例子,例如早期微信充值手機花費的早期處理思路,就是提示“充值操作完成,具體結果稍後通知” (現在已經改了,頁面等待即會通知)

悲觀/樂觀鎖 使用場景

基本概念

悲觀

阻塞(等待),超時報錯

  • 假設會衝突,好處是能保持數據一致性,設計思想是不管咋樣先無腦上鎖
    ,說人話就是“我每次出門都先帶一瓶防狼噴霧,不管我會不會遇到危險情況,我假設可能我被壞蛋盯上了”顯而易見,這樣我出門花費的時間成本肯定增加了,代碼層面就是耗費的性能增加了

樂觀

假設不衝突,提交更新對比版本號,失敗報錯,設計思想就是是儘量減少鎖的使用

  • 說人話就是“出門不帶防狼噴霧了,我覺得世界壞蛋不多

  • 高併發的修改操作,樂觀會頻繁更新衝突報錯,如果你邏輯寫了重試操作,那麼久一直報錯重試N循環,這時候已經不適用樂觀,應該使用悲觀

結合場景

  • 用戶下單,醫生開方,規模到達一定量時,肯定要保證不要出現“超賣”現象,因此扣減庫存使用悲觀無可厚非
  • 其他場景,如基礎字典數據維護,用戶修改個人信息,扣減用戶餘額等一系列操作,一般穩妥期間都會加上樂觀鎖,其場景就是併發量並不大

實際代碼應用

這種鎖機制,不管你用什麼基本都很成熟了

針對數據庫,我這裏推薦的sqlsugar這個ORM,使用sqlsugar能夠很容易的針對數據庫表進行樂觀/悲觀鎖的操作,其穩定和成熟性也經過了多年多家大頭公司認可了,使用方法看官方文檔很詳細

如果是分佈式鎖,這裏推薦的是FreeRedis它裏面有基於redis封裝好了分佈式鎖的使用,調用十分簡便,我個人實際公司業務上也是使用了這個

爲了解決A問題而帶來的B問題解決方案

引子:

通過上訴解決方案後,理論上技術層面性能問題頂住沒啥問題了

(這如果還有問題,想必你司業務及其牛X,更進階的方案也沒啥實際上的技術思路提升,無非就是把處理業務的模塊繼續拆分,拆分後的各個粒度更小的業務服務再加大規模的集羣,也就是現在大廠普遍的微服務)

但是可能會有一個新的問題,例如:A客戶看中一個熱門商品滿心期待的去下單,下單完心裏美滋滋幻想着用上這個商品然後去睡覺,第二天起來纔看到 “對不起,下單失敗,庫存不足”,直接各種惡毒的語言開始詛咒開發這個產品的人

某些業務場景下這種情況是允許的,而在某些產品上,這種情況則是不被允許存在的,實際解決其實也簡單,如果項目有ws,可以考慮在頁面等待ws獲取結果,如果沒有則輪詢請求某個api返回最終結果

有沒有發現,我本來 “普通一個接口搞定的事情,現在爲了解決‘可能存在的’問題要做的事情反而多了”所以具體公司業務開發的時候,更多的是要掌握好實際需求以及實際預估場景,一句話自己根據實際場景把握好,“編程永遠沒有萬金油”

這就是現如今利用各類技術解決問題後,衍生出來的新問題,因此請實實在在的確保你的項目實際上存在這麼大的流量和高併發,真真切切存在此類問題需要解決,才考慮這些技術手段的解決方案,千萬不要成爲段子中的:“技術上異步填谷削鋒,運行時用戶白天20晚上15” 我經常提醒自己,“不要爲了寫代碼而寫代碼”

以上就是我對類似的處理的宏觀處理思想以及關鍵點位的實際處理方式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章