背景交易系統(tǒng)可能不是技術(shù)難度最深的,但是業(yè)務復雜度最高的,一個訂單從提交到最后真正生產(chǎn)成功要經(jīng)歷幾十個系統(tǒng),涉及的接口交互,MQ等可能達上百個。任何一個環(huán)節(jié)出問題都會導致這一單的異常,而且交易不像單純的資訊門戶可以靠靜態(tài)化或者緩存抗住大并發(fā),交易系統(tǒng)里面涉及到大量的資源(庫存,優(yōu)惠券,優(yōu)惠碼等)消費,訂單生成等需要寫入持久化的操作不是單純的異步或者緩存化可以解決的,而且對庫存等敏感信息不能出現(xiàn)并發(fā)扣減等。 細節(jié)的設(shè)計非常多,下面挑出比較典型的一些方面,給大家介紹下京東到家交易系統(tǒng)的架構(gòu)設(shè)計和關(guān)鍵問題的處理方案。 歷程系統(tǒng)Set化初期的訂單系統(tǒng)和首頁,單品頁,購物車業(yè)務邏輯層等都是在一個大項目里。非常適合初期人員少,業(yè)務復雜度低,快速迭代,不斷探索試錯的過程,但是隨著業(yè)務的發(fā)展,出現(xiàn)了以下問題:
解決方案 分庫分表問題 解決方案 另外下發(fā)到個人中心數(shù)據(jù)庫的訂單信息,每天不斷的累計到DB中,存在以下風險:
目前我們采取對個人中心的表按照pin進行分庫分表。 這種場景下我們采用了ES,在寫入DB的時候同步寫入ES。你可能會問ES失敗了,數(shù)據(jù)不一致怎么辦,ES失敗了DB回滾,Worker標識狀態(tài),重新迎接下一次輪詢。 前端下單和后端生產(chǎn)分離問題 解決方案 我們ToC的訂單系統(tǒng)和ToB的是兩個不同的獨立數(shù)據(jù)庫,互不影響;訂單管道的Woker都是基于TBSchedule的分布式管理,多個Woker并行處理,下發(fā)時機都在毫秒級; 并行控制提升效率問題 解決方案 另外資源(庫存,優(yōu)惠券,優(yōu)惠碼,促銷等)的消費和回滾,我們也采用了并行的方式,每一種資源類都實現(xiàn)消費和回滾的接口。如下圖: 每個資源類都是一個Task的成員變量,Task實現(xiàn)了Callable接口。這樣一來,不但整個提單大接口的效率提升了,對于資源消費和回滾環(huán)節(jié),程序和業(yè)務的擴展性提升了很多。比如新增一種資源,這時候只需實現(xiàn)消費和回滾接口,然后扔到線程池里面就完成了。 異步在服務端可能需要針對提單請求做一些附屬的事情,這些事情其實用戶并不關(guān)心或者用戶不需要立即拿到這些事情的處理結(jié)果,這種情況就比較適合用異步的方式處理這些事情,思路就是將訂單交易的業(yè)務整理出來,哪些是不影響主流程的,例如:發(fā)短信,保存最近使用地址,清除購物車商品,下發(fā)訂單給個人中心等等。這些都是在提單之后的異步線程去做。對于下發(fā)給個人中心的操作,如果失敗,我們會有Woker補償機制; 我們這里使用的是線程池的模式進行異步處理的,處理過程中有幾個問題需要注意下:
依賴治理訂單交易上百個接口,幾十個系統(tǒng)交互。各服務直接的依賴關(guān)系如何治理是一個很重要的問題。如下圖: 問題 解決方案 我們解決此類問題是使用自己開發(fā)的基于Zookeeper的“魯班系統(tǒng)”,其原理就是Zookeeper相應的Znode節(jié)點下的數(shù)據(jù)做為對接口的開關(guān)或者降級情況的配置等。當相應的節(jié)點的數(shù)據(jù)發(fā)生變化的時候,對此節(jié)點監(jiān)聽的所有服務器都會受到通知,并將此變更同步到本地的緩存中;本地緩存我們使用的ConcurrentHashMap。當然也可以使用Guava Cache等開源組件,注意并發(fā)的場景就可以了; 然后再結(jié)合我們的UMP監(jiān)控系統(tǒng)對系統(tǒng)的可用率,調(diào)用量等情況進行降級時機的判定,對Zookeeper相應節(jié)點的數(shù)據(jù)做動態(tài)配置; 履約問題 解決方案 此系統(tǒng)大大提升了我們定位解決問題的效率。 未來展望多渠道分拆微信,app,h5等多渠道隔離,單獨部署單獨發(fā)布。各渠道互不影響。以后再灰度就要單臺->單set->單渠道->全量 監(jiān)控畫了一個效果圖,服務依賴的治理根據(jù)透明可視化。一個大服務依賴的接口眾多,如果像下面我畫的這個圖這樣,不同顏色代表不同的接口狀態(tài)。鼠標附上去會展示詳細信息;以后還可以做成,圖形和后臺服務程序聯(lián)動,圖中的一個節(jié)點就是一個服務,通過拖拽等方式,實現(xiàn)和后臺程序聯(lián)動達到降級的效果; 接單xml數(shù)據(jù)化如果以后訂單量持續(xù)增加,每次操作多張表,單量上升的時候系統(tǒng)壓力會上升,我們可以對訂單庫的表數(shù)據(jù)存儲進行XML化,每個訂單只操作一張表,存儲一條數(shù)據(jù),(XML化相對JSON可能解析的時候性能會稍微差一些,但是對于問題的查詢可視化程度更高)然后在下發(fā)到后臺的ToB生產(chǎn)數(shù)據(jù)庫的時候,異步Worker還原成多表; 結(jié)算頁緩存化這個其實我們已經(jīng)有技術(shù)方案,流程圖已經(jīng)出來了。后期就會上。目前提單的時候眾多參數(shù)是從結(jié)算頁從URL里面帶過去的。雖然我們做了數(shù)字簽名但是,在安全性和接口數(shù)據(jù)傳輸效率上還不是最好的。大致方案就是在用戶進入結(jié)算頁后將數(shù)據(jù)緩存化,當用戶刷新結(jié)算頁的時候,非敏感信息直接從緩存取,不用重復調(diào)用接口,提交訂單的時候也入?yún)⒕秃芎唵瘟?,一個Key就可以了。 |
|