電商系統-業務中台


業務中台

訂單中心

1)異步化

場景:大促期間新增許多需要獲取訂單狀態的服務,比如應對雙11而臨時增加的數據中台訂單大屏展示等
解決:異步化,並對消息隊列調優,多隊列分流
問題:注意異步化引發的亂序問題,一是傳輸階段,二是消費階段

rabbitmq傳輸:隊列級別順序保障,單消費者消費一個隊列可以嚴格保障順序性,需要擴充隊列數提
升性能

kafka傳輸:分區級別順序保障,只能保障投放和傳輸階段的順序性

consumer:1對1消費存在性能問題,接收消息后對key做二次分發,放入多個內存隊列,開啟多線程
消費

2)過期訂單

雙11搶單是最常見的場景,搶單不支付會占據大批量資源,如商品庫存。如何取消過期訂單是架構師必須面對的問題。主要有以下幾種方案:

掃表實現

原理:通過定時任務輪詢掃描訂單表,超時的批量修改狀態
優點:實現非常簡單
缺點:

  • 大量數據集,對服務器內存消耗大。
  • 數據庫頻繁查詢,訂單量大的情況下,IO是瓶頸。
  • 存在延遲,間隔短則耗資源,間隔長則時效性差,兩者是一對矛盾。
  • 不易控制,隨着定時業務的增多和細化,每個業務都要對訂單重復掃描,引發查詢浪費

java延遲隊列實現

原理:通過DelayQueue,每下一單,放入一個訂單元素並實現getDelay()方法,方法返回該元素距離失效還剩余的時間,當<=0時元素就失效,就可以從隊列中獲取到。啟用線程池對數據監聽,一旦捕獲失效訂單,取出之后,調用取消邏輯進行處理。

優點:基於jvm內存,效率高,任務觸發時間延遲低。
缺點:

  • 存在jvm內存中,服務器重啟后,數據全部丟失。
  • 依賴代碼硬編碼,集群擴展麻煩
  • 依賴jvm內存,如果訂單量過大,無界隊列內容擴充,容易出現OOM
  • 需要代碼實現,多線程處理業務,復雜度較高
  • 多線程處理時,數據頻繁觸發等待和喚醒,多了無謂的競爭

消息隊列實現

原理:設置兩個隊列,每下一單放一條進延遲隊列,設定過期時間。消息一旦過期,獲取並放入工作隊列,由consumer獲取,喚起超時處理邏輯

如果采用的是RabbitMQ,其本身沒有直接支持延遲隊列功能,可以針對Queue和Message設置 x-
message-ttl,用消息的生存時間,和死信隊列來實現,具體有兩種手段, A: 通過隊列屬性設置,隊列
中所有消息都有相同的過期時間,粗粒度,編碼簡單 B: 對消息進行單獨設置,每條消息TTL可以不同,細粒度,但編碼稍微復雜。

優點:

  • 可以隨時在隊列移除,實現實時取消訂單,及時恢復訂單占用的資源(如商品)
  • 消息存儲在mq中,不占用應用服務器資源
  • 異步化處理,一旦處理能力不足,consumer集群可以很方便的擴容

缺點:

  • 可能會導致消息大量堆積
  • mq服務器一旦故障重啟后,持久化的隊列過期時間會被重新計算,造成精度不足
  • 死信消息可能會導致監控系統頻繁預警

redis實現

原理:利用redis的notify-keyspace-events,該選項默認為空,改為Ex開啟過期事件,配置消息監聽。每下一單在redis中放置一個key(如訂單id),並設置過期時間。

優點:

  • 消息都存儲在Redis中,不占用應用內存
  • 外部redis存儲,應用down機不會丟失數據
  • 做集群擴展相當方便
  • 依賴redis超時,時間准確度高

缺點:訂單量大時,每一單都要存儲redis內存,需要大量redis服務器資源

被動取消

原理:在每次用戶查詢訂單的時候,判斷訂單時間,超時則同時完成訂單取消業務。
優點:

  • 實現極其簡單
  • 不會有額外的性能付出
  • 不依賴任何外部中間件,只是應用邏輯的處理

缺點:延遲度不可控,如果用戶一直沒觸發查詢,則訂單一直掛着,既不支付也未取消,庫存也就被占着

支付中心

支付交互流程

1)重復支付

原因:在第一步發起的時候,用戶進入支付方式選擇頁。選第一個支付方式並支付完后因為通知延遲,以為支付失敗。在支付又選了第二種,再次支付。

應對方案:

  • 程序屏蔽,前端js觸發按鈕置灰或者遮罩提示(支付成功?遇到問題?),或者在支付方式選擇頁直接跳轉。
  • 后端處理,發現不同通道下的支付成功回調,拋消息隊列或記錄日志。

數據修復:
首先查支付日志,確認針對同一筆訂單收到了不同支付渠道的回調。
其次,在支付平台管理后端可以查到入賬記錄,人工介入。
最后對賬階段會發現對方多帳,我方補單時出現重復訂單。

問題處理:調取退款接口或者在支付渠道的管理后台操作退款(一定要多次確認無誤)。

2)異常訂單

支付但未開單

場景:用戶明明支付成功,但未開通訂單

問題分析:
一般支付渠道會間隔性多次回調開單鏈接,如果支付未開單,銀行未回調的可能性比較小,着重排查開單接口是否可用。如果可用追查日志是否出現異常記錄。

應對措施:

  • 對賬階段可以查漏,程序自動完成補單,但是處理相對延遲,取決於支付渠道的對賬文件下發周期
  • 人工補單,人工查詢支付渠道后台數據,確認已支付的情況下,介入補單流程人工處理

未支付但已開單

場景:用戶未支付,或者財務中心未收到這筆款項,訂單狀態已開通。這種就問題比較嚴重了
應對措施:首先排除人為操作因素。其次排查系統是否存在漏洞或者級聯開單的情況

3)回調延遲

場景:用戶是期望支付完成的同時立馬看到結果。但是中間多層遠程的調用,可能發生訂單狀態更新延遲問題。

解決:主動查詢。在用戶查看訂單的時候,如果是類似“支付中”的中間態時,觸發遠程訂單狀態查詢接口。

4)支付路由

背景:
保障支付可用性及支付分流,支付中心對接多家渠道

方案:

  • 支付中心對接多個支付渠道,支付寶,微信,各銀行或第三方支付供應商
  • 對不同用戶,進入支付方式選擇頁時,做支付分流
  • 做好監控統計,一旦某個支付渠道不可用或者延遲較大,切掉,下線,或者降權

營銷中心

1)概述

大促和活動不分家,一般營銷中心所面對的主要是促銷策略、優惠方式等業務上的架構問題。

從促銷活動的范圍來看,分為單品促銷活動、套裝促銷活動、店鋪促銷活動,平台促銷活動。
從促銷類型來看,分為滿減、折扣、贈品等。

業務復雜度高,一般遵循 “同類營銷僅可選其一,不同類營銷可疊加” 的規則。同類疊加意義不大且會造成系統復雜度上升,引發用戶困惑。

2)前端設計

用戶體驗上的設計,比如購物車里商品的排序,按商鋪分門別類。優惠總價格及時調整。這些依賴於前端的ui設計和交互體驗。

3)贈品設計

(SPU , SKU 基礎概念)
贈品有兩種設計方案,一種是不做單獨的SKU,只有一個空的描述,設計簡單,缺點是沒有商品詳情
頁,無法給用戶直觀的查看和估值。

另一種是單獨做SKU,贈品也會作為一個商品存在,與主商品關聯,下單的時候將會自動加到商品列
表,價格降為0。這種更為常見。整個商品有完善的詳情頁,用戶可以直接看到價格甚至單獨下單購
買。

4)排他與優先級

檢查同類別促銷,將最大優惠力度的規則應用到訂單,並且滿足排他性,同類只享受其一。比如滿10減3,滿20減5,那么用戶購買大於20時,只減5即可。
不同類別不做排斥,如購物車整體滿減后,不影響單個商品的折扣。在記錄數據時,優惠要細化到每個單獨的訂單明細上。退款也做到明細級別的單獨退。

5)價格分攤

滿減或平台券等優惠,在多個商品下單時,涉及到金額的分攤。即 優惠總額度/購物車總額 ,得到比例后再按比例均分到每個商品。只有分攤才能在發生部分退款時退回真實金額。
但是這會涉及到一個精度問題。舉例如下:滿99減9活動,假設用戶購買了 30+40+50=120,3件商品
應付111元。按比例折算的話,9/99取4位小數是0.9090,那么分攤后為
30x0.9090+40x0.9090+50x0.9090=109.08與實際支付金額出現偏差。這會造成財務無法平賬。
解決方案:記賬時在訂單明細記錄,將誤差 111-109.08=1.92計入金額最大的明細,也就是50元商品
上。那么最終記賬為:30x0.9090 + 40x0.9090 +(50*0.909+1.92)= 111

6)退單處理

退單后要同時恢復用戶的權益,比如優惠券的再次使用,限購次數等。確保用戶體驗。

商品中心

1)限時商品的下架控制

這個和超時訂單設計方案類似

2)庫存管理

普通商品可以直接借助數據庫鎖實現,一般分樂觀鎖和悲觀鎖兩種方案,如果采用悲觀鎖(如select語
句帶forupdate),會帶來很大的性能阻塞,所以更多的采用樂觀鎖設計。

樂觀鎖就是在最后執行庫存扣減操作時,將事務開始前獲取的庫存數量帶入到SQL語句中作為更新的
where條件,如果數量相等,則該條更新庫存的語句成功執行返回update條數為1;如果不相等,則表
示該商品的庫存信息已經被其他事務修改,需要放棄該條update的執行,采用重試處理。

庫存秒殺商品因為大批量的訪問在一瞬間涌入,數據庫扛不住。可以采用 redis緩存做decr處理,正常
下單后,再使用mq異步更新到db。(秒殺不超賣課題的庫存控制)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM