場景 業務場景:下單時扣減庫存,由於比較簡單,商品和庫存都放到了一個上下文中 學習多個上下文之間的交互,協作,訂單上下文生成訂單時,扣減商品上下文中的庫存 第一個方法 第一個方法的技術選型,Redis,WebApiClient,EF CORE, Polly, ExceptionLess,雪花演算法 把 ...
場景
業務場景:下單時扣減庫存,由於比較簡單,商品和庫存都放到了一個上下文中
學習多個上下文之間的交互,協作,訂單上下文生成訂單時,扣減商品上下文中的庫存
第一個方法
第一個方法的技術選型,Redis,WebApiClient,EF CORE, Polly, ExceptionLess,雪花演算法
把商品的庫存放到redis中,在redis中驗證庫存,redis中扣減庫存,生成訂單後使用WebApiClient調用商品上下文中扣減庫存的介面
問題:
1,在redis中驗證庫存,扣減庫存時,需要加上Look,多線程時,獲取redis中的庫存時不加鎖獲取的庫存可能不正確
2,確保WebApiClient調用介面能成功,使用polly 如果掉介面異常,失敗時,重試,重試過程中記錄異常,和重試的次數,併發出通知。
3,性能不強,EF core 需要持久化訂單的數據,使用WebApiClient調用商品上下文中的介面有網路開銷
4,WebApiClient請求異常,失敗時,Polly會進行重試,出現多次調用的問題,商品上下文介面必須做冪等
5,如何保證不超賣,執行扣減庫存修改語句是帶上庫存必須大於0的條件
第二個方法
第二個方法的技術選型,Redis,CAP,Rabbitmq,EF CORE, Polly,ExceptionLess,雪花演算法
把商品的庫存放到redis中,在redis中驗證庫存,redis中扣減庫存,生成訂單時開啟事務,使用CAP來發送消息到EventBus,商品上下文訂閱,扣減庫存
問題:
1,如果保證消息不丟,使用CAP,CAP是基於本地消息表的方式來實現的組件,發送消息和消費消息都已本地事務的方式記錄了發送和消費的情況,如果失敗
會進行重試,重試一定的次數,可以人工干預解決問題,也可以做補償事件,
2,訂閱消息時可能出現異常,CAP會進行重試,同一消息會出現多次消費的問題,商品上下文介面必須做冪等
3,CAP在發送,消費消息時都會已本地事務的方式,寫入一條信息到資料庫表中,進行了2次IO的交付
第三個方法
第三個方法的技術選型,Redis,Rabbitmq,CAP,EF CORE, Polly,ExceptionLess,雪花演算法
之前看過一句話,
讀多寫少用緩存,寫多讀少用隊列
,我們可能使用隊列來提高我們的處理能力,隊列可以堆積消息,所以要使用消息隊列使用CommandService來發送Command,DomainEventService來發送事件,CAP具有EventBus的功能,但是多了2次IO的交互,使用自己簡單封裝Rabbitmq來寫CommandService
事件會改變我們系統的狀態,代表已經發生過的事實,比較重要,為了確保全全選擇了CAP
當前端調用我們介面時在Controller中使用CommandService發送command到EventBus,commandHandler訂閱消息,在redis中驗證庫存,redis中扣減庫存,生成訂單時開啟事務
使用DomainEventService來發送消息到EventBus,商品上下文訂閱,扣減庫存
問題:
1,CommandService的實現,參考Rabbitmq官網的demo以及文檔,參考CAP源碼
2,使用隊列後,沒有獲取到返回值,通過記錄日誌,查看消息的消費情況
3,大大增強了框架的複雜性,查錯比較複雜
4,Rabbitmq沒有使用集群,web也沒有使用集群,數據沒有集群,目前對於集群的學習比較淺