導(dǎo)讀
隨著京東業(yè)務(wù)增長(zhǎng)、平臺(tái)商家數(shù)的大幅增加,京東的訂單量急劇上漲,尤其是2025年京東發(fā)力本地生活業(yè)務(wù),給B端訂單存儲(chǔ)帶來(lái)較大壓力;另一方面京喜自營(yíng)做為京東低價(jià)策略心智的店鋪,業(yè)務(wù)增長(zhǎng)也是非常迅猛,一個(gè)店鋪訂單相當(dāng)于幾十近百個(gè)店鋪單量總和。基于以上訂單ES存儲(chǔ)面臨極大挑戰(zhàn),系統(tǒng)架構(gòu)升級(jí)迫在眉睫。
本文主要介紹B端pop訂單異構(gòu)系統(tǒng)當(dāng)前系統(tǒng)架構(gòu)現(xiàn)狀,闡述下我們面臨的主要問題、以及解決思路和技術(shù)升級(jí)方案(后續(xù)持續(xù)更會(huì)有更多的技術(shù)方案細(xì)節(jié)文章);一方面為了介紹下我們當(dāng)時(shí)解決問題的一些心路歷程,另一方面也未了能讓大家更好的了解目前這套運(yùn)行了多年的系統(tǒng)為什么以這種形式存在、以及目前我們遇到的核心問題有哪些,對(duì)于訂單ES架構(gòu)存儲(chǔ)的升級(jí)方案是什么樣的。
一、系統(tǒng)現(xiàn)狀
1.1 業(yè)務(wù)背景介紹:
POP訂單ES最早定位是對(duì)商家提供待履約訂單查詢服務(wù)(非C端檢索)。系統(tǒng)核心是寫和讀兩個(gè)服務(wù),寫服務(wù)消費(fèi)訂單管道消息、pop訂單JED的binlog、OFW的ODC變更消息、臺(tái)賬系統(tǒng)對(duì)賬消息等更新訂單ES數(shù)據(jù);讀服務(wù)提供訂單列表(商家維度)、訂單詳情的檢索服務(wù)。
系統(tǒng)之初僅支持已付款且達(dá)到可履約狀態(tài)的訂單(不包含未付款訂單)檢索,用戶商家訂單履約,主要服務(wù)于開放訂單API檢索及京麥端訂單檢索。隨著業(yè)務(wù)的發(fā)展,后續(xù)消費(fèi)了提單、訂單拆分、預(yù)售訂單等消息,對(duì)未付款訂單、預(yù)售訂單存儲(chǔ)、兼容處理。
隨著百萬(wàn)商家項(xiàng)目推進(jìn),服務(wù)商、自研KA商家及中小開發(fā)者對(duì)開放API提出了更多的訴求,期望能夠通過更少的接口獲取更多的數(shù)據(jù),提升開發(fā)者對(duì)接及日常維護(hù)效率,開放平臺(tái)側(cè)啟動(dòng)開放RESTful API項(xiàng)目,其中訂單做為商家的核心業(yè)務(wù)數(shù)據(jù),歷史開放接口不夠內(nèi)聚,開發(fā)者需要多個(gè)接口才能獲取完整的訂單信息,基于以上pop訂單還異構(gòu)了發(fā)票、promise、售后、評(píng)價(jià)等系統(tǒng)的狀態(tài)信息,這些都給POP訂單ES存儲(chǔ)帶來(lái)較大的挑戰(zhàn)。
1.2 系統(tǒng)架構(gòu)簡(jiǎn)介:
?應(yīng)用層做業(yè)務(wù)處理,寫服務(wù)負(fù)責(zé)消費(fèi)上游各方MQ處理業(yè)務(wù)務(wù)處理,之后調(diào)用代理層服務(wù)更新訂單信息;讀服務(wù)核心對(duì)外提供訂單列表、詳情兩個(gè)服務(wù)。大促高峰時(shí)可達(dá)到每分鐘70萬(wàn)次更新寫入,每分鐘50萬(wàn)的檢索查詢;
?代理層負(fù)責(zé)數(shù)據(jù)路由、讀取與寫入。劃分為熱集群讀寫代理、歸檔集群讀寫代理。熱集群通過設(shè)置不同topic分組隔離消費(fèi)實(shí)現(xiàn)雙流架構(gòu),匯天廊坊互為主備保證系統(tǒng)高可用。讀服務(wù)支持動(dòng)態(tài)路由配置,可根據(jù)ES負(fù)載情況動(dòng)態(tài)分配流量,如匯天、廊坊各百分之50流量,或匯天20%,廊坊80%;同時(shí)可以將某個(gè)商家查詢流量路由到固定機(jī)房。目前歸檔集群考慮成本暫時(shí)并未升級(jí)至雙流架構(gòu),通過ES副本機(jī)制來(lái)保障高可用。
?存儲(chǔ)層采用ES做為存儲(chǔ)介質(zhì),分為熱集群、歸檔集群;熱集群存儲(chǔ)近8個(gè)月的訂單數(shù)據(jù),單個(gè)集群有98個(gè)節(jié)點(diǎn)(3個(gè)主節(jié)點(diǎn),10個(gè)網(wǎng)關(guān)節(jié)點(diǎn),85個(gè)數(shù)據(jù)節(jié)點(diǎn))。集群中共計(jì)12個(gè)索引,其中11個(gè)KA索引(存儲(chǔ)大商家訂單數(shù)據(jù)),每個(gè)索引只有1個(gè)主分片(1副本);普通商家索引有96各數(shù)據(jù)分片(1副本);冷集群存儲(chǔ)了16年至2024年所有的訂單數(shù)據(jù),每年創(chuàng)建一個(gè)索引,每個(gè)索引96分片(1副本)。
pop訂單改造前的架構(gòu)圖如下:(為方便讓大家更好理解,本圖會(huì)忽略一些細(xì)節(jié)便于大家理解):
?

?
二、系統(tǒng)當(dāng)前的核心痛點(diǎn)
1、目前POP訂單ES存在較嚴(yán)重的數(shù)據(jù)傾斜問題,由于是B端訂單檢索為了不跨索引和分片檢索數(shù)據(jù),是以venderId維度進(jìn)行路由分片,確保同一個(gè)商家的訂單數(shù)據(jù)存儲(chǔ)在同一個(gè)分片。但商家的經(jīng)營(yíng)情況差異較大,如上邊所說(shuō)京喜自營(yíng)做為一個(gè)京東自己運(yùn)營(yíng)的店鋪,訂單體量可以占到總訂單量的1/4,類似于這樣的大商家落到一個(gè)數(shù)據(jù)分片會(huì)導(dǎo)致某個(gè)數(shù)據(jù)分片存儲(chǔ)超級(jí)大,最大的數(shù)據(jù)分片已經(jīng)到了1TB以上。大商家的一個(gè)復(fù)雜檢索查詢會(huì)對(duì)所有在該分片上的商家產(chǎn)生較大性能波動(dòng),同時(shí)若硬件故障大分片數(shù)據(jù)在恢復(fù)遷移時(shí)都是在災(zāi)難性的。下邊是升級(jí)前匯天集群部分分片數(shù)據(jù)的統(tǒng)計(jì)信息,數(shù)據(jù)差異達(dá)5倍之多。
?

2、隨著業(yè)務(wù)增長(zhǎng),自身的訂單ES數(shù)據(jù)量持續(xù)增加,部分分片數(shù)據(jù)高達(dá)1TBG以上,ES官方推薦分片數(shù)據(jù)在50-100G,已經(jīng)是官方推薦值的50倍。京喜自營(yíng)訂單屬于二段單邏輯,C端京喜大店下單,訂單會(huì)由供貨商去履約,供貨商同時(shí)還會(huì)是京東的一個(gè)pop商家,這個(gè)訂單在京喜店鋪存儲(chǔ)一份,同時(shí)會(huì)在供應(yīng)商店鋪下會(huì)在存儲(chǔ)一份,京喜大店業(yè)務(wù)給整個(gè)存儲(chǔ)帶來(lái)了0.5倍增長(zhǎng)。

3、ES的核心數(shù)據(jù)源是上游訂單數(shù)據(jù)庫(kù)的binlog消息,隨著業(yè)務(wù)不斷迭代,接入了更多的消息如:order_submit(提單)、delete_parent_order(拆單)、orderpipe_edit_v2(管道修改)、ODC(鎖定、解鎖、取消)、order_state_zanting(暫停)、afs_status(售后狀態(tài))、comment_change(備注變更)等將近10+的消息。訂單ES更新頻次持續(xù)增加,每分鐘高達(dá)30萬(wàn),每新增一個(gè)MQ消費(fèi),每個(gè)訂單至少會(huì)增加1次更新操作。ES的更新沖突明顯增加,對(duì)于訂單檢索的時(shí)效性也帶來(lái)了很大壓力。

4、數(shù)據(jù)維護(hù)成本高,目前我們有冷熱兩個(gè)集群,每年兩次大促前需要將熱集群中超過5個(gè)月以上的訂單遷移至歸檔集群,這個(gè)過程相對(duì)比較繁瑣耗時(shí)長(zhǎng),DUCC變更、遷移數(shù)據(jù)、比對(duì)數(shù)據(jù)、灰度切流等等。周期較長(zhǎng)主要是以下兩個(gè)原因:
1.數(shù)據(jù)遷移范圍強(qiáng)依賴上游訂單JED線上庫(kù),速度過快對(duì)線上有影響,同時(shí)還會(huì)反查ES數(shù)據(jù)比對(duì)給線上ES也帶來(lái)較大查詢壓力,導(dǎo)致無(wú)法再白天運(yùn)行。
2.整個(gè)寫入過程均為單個(gè)訂單寫入、刪除ES,過程中會(huì)產(chǎn)生大量的Segment merge,將小段合并成大段,會(huì)影響寫入性能,導(dǎo)致正常訂單更新延遲。

三、解決方案
3.1 數(shù)據(jù)傾斜問題
數(shù)據(jù)傾斜問題核心是我們采用了venderId進(jìn)行路由,商家的體量不可控,在最初相關(guān)同學(xué)已經(jīng)考慮到了這種情況,在熱集群中創(chuàng)建了對(duì)應(yīng)的單獨(dú)索引進(jìn)行隔離,但當(dāng)時(shí)這個(gè)索引創(chuàng)建的時(shí)候只有一個(gè)shards,數(shù)據(jù)集中在一個(gè)分片上,并不能解決數(shù)據(jù)傾斜問題(數(shù)據(jù)仍集中在一個(gè)分片上,可能考慮跨分片聚合數(shù)據(jù)的性能問題)。
1.物理層隔離,降低影響:為大商家申請(qǐng)獨(dú)立集群進(jìn)行存儲(chǔ),在獨(dú)立集群中為每個(gè)商家創(chuàng)建獨(dú)立索引并根據(jù)體量配置不同的分片數(shù)量。代理層增加大商家虛擬路由邏輯,將大商家的請(qǐng)求routing到獨(dú)立集群中指定索引,降低了大商家對(duì)其他商家?guī)?lái)的不確定性影響。
2.靈活的路由分片策略:原有路由策略僅支持商家維度,在代理層對(duì)集群分片路由規(guī)則做擴(kuò)展支持,針對(duì)大商家存儲(chǔ)集群的分片路由商家維度升級(jí)為訂單維度,根據(jù)訂單號(hào)進(jìn)行路由保證各分片數(shù)據(jù)的均等。

3.2 集群中單數(shù)據(jù)分片過大問題
ES官方建議單分片數(shù)據(jù)控制在50-100G,同時(shí)ES集群節(jié)點(diǎn)(網(wǎng)關(guān)、主節(jié)點(diǎn)、數(shù)據(jù)節(jié)點(diǎn))數(shù)量控制在100個(gè)以內(nèi)(故障恢復(fù)時(shí)長(zhǎng)考慮,可參考附錄5)。基于這兩個(gè)原則,單集群已無(wú)法滿足存儲(chǔ)訴求,當(dāng)時(shí)也考慮了更換存儲(chǔ)介質(zhì),考慮到端上豐富的查詢?cè)V求,團(tuán)隊(duì)內(nèi)部研討后決定繼續(xù)采用ES。
我們決定將熱集群中普通商家的ES集群由1個(gè)擴(kuò)展至3個(gè)(基于當(dāng)前業(yè)務(wù)發(fā)展及成本綜合考量決定)。在數(shù)據(jù)代理層擴(kuò)展集群路由邏輯,基于商家id哈希將商家數(shù)據(jù)分散到3個(gè)ES集群。

3.3 ES頻繁更新的問題
當(dāng)前系統(tǒng)采用了ES的樂觀鎖更新機(jī)制,在收到上游消息后,第一步獲取ES版本號(hào),第二部設(shè)置更新字段,第三部保存更新,保存更新版本沖突會(huì)發(fā)送一個(gè)重試MQ進(jìn)行重試。
經(jīng)過分析訂單變?yōu)榇鰩?kù)前的消息比較集中,上游各系統(tǒng)基本都是同步消費(fèi)訂單管道消息完成業(yè)務(wù)操作后對(duì)外廣播消息,這些消息同時(shí)到達(dá)我們系統(tǒng),一方面存在并發(fā)沖突問題,第二方面是給ES帶來(lái)了較大的更新壓力。為了降低ES的更新壓力,考慮增加一個(gè)擋板對(duì)消息進(jìn)行匯總整型降低ES的更新次數(shù),同時(shí)減少ES的更新沖突問題。

3.4 日常數(shù)據(jù)維護(hù)成本高的問題
受限于ES集群節(jié)點(diǎn)數(shù)量是有上限,大促前都需要對(duì)熱集群訂單數(shù)據(jù)進(jìn)行歸檔操作,由熱集群遷移至冷集群。系統(tǒng)初始是通過一個(gè)歸檔任務(wù)來(lái)進(jìn)行遷移操作。首先圈定遷移數(shù)據(jù)的范圍逐條讀取--->逐條寫入歸檔集群--->比對(duì)數(shù)據(jù)無(wú)誤--->刪除熱集群數(shù)據(jù)。業(yè)務(wù)高峰期無(wú)法操作,新增、修改、刪除對(duì)頻繁刪除會(huì)產(chǎn)生很多的段文件,ES定期對(duì)段文件進(jìn)行merge操作(詳情可參照附錄部分內(nèi)容),單次數(shù)據(jù)遷移大概耗時(shí)1個(gè)月左右時(shí)間,操作過程也較繁瑣。我們的目標(biāo)是全流程自動(dòng)化的數(shù)據(jù)遷移無(wú)需人工介入,僅需要關(guān)注相關(guān)業(yè)務(wù)監(jiān)控即可。考慮到資源及ROI問題,數(shù)據(jù)遷移改造共經(jīng)歷了兩個(gè)階段:
第一階段通過通過reindex方式遷移數(shù)據(jù),然后通過回放歸檔消息的方式追齊過程中的數(shù)據(jù)變更。該方案一定程度縮減了整體的時(shí)間及工作量,相較之前效率上大幅提升,時(shí)間大概由原來(lái)的20多天縮減至10天左右。

第二階實(shí)現(xiàn)數(shù)據(jù)歸檔的全流程自動(dòng)化操作。新建歸檔ES緩存,每天一個(gè)索引,把每天訂單變更記錄保存至索引中。通過一個(gè)定時(shí)任務(wù)批量讀取、比對(duì)、寫入同時(shí)刪除原集群中數(shù)據(jù)。

3.4 終局方案
本次升級(jí)通過 “租戶分級(jí)隔離 + 雙層 Hash 路由 + 差異化分片策略 + 雙活物理底座” 的組合拳,成功構(gòu)建了一個(gè) 高性能、高擴(kuò)展、高可用 的企業(yè)級(jí)訂單檢索與分析平臺(tái),完美支撐了業(yè)務(wù)量的爆發(fā)式增長(zhǎng)。
?

四、附錄:
4.1 超大集群維護(hù)的挑戰(zhàn)
ES 是一個(gè) P2P(對(duì)等)架構(gòu)的分布式系統(tǒng),雖然有 Master 節(jié)點(diǎn),但所有節(jié)點(diǎn)都需要保存集群的狀態(tài)。核心瓶頸:Cluster State(集群狀態(tài))的廣播
ES 的 Master 節(jié)點(diǎn)負(fù)責(zé)維護(hù) Cluster State(包含所有索引的 Mapping、Setting、分片路由表等元數(shù)據(jù))。
每一次變更(如創(chuàng)建索引、Mapping 變更、節(jié)點(diǎn)上下線),Master 都要把更新后的 Cluster State 廣播給集群內(nèi)的所有節(jié)點(diǎn);所有節(jié)點(diǎn)收到后,都需要向 Master 確認(rèn)(Ack)。
當(dāng)節(jié)點(diǎn)數(shù)超過 100 時(shí)會(huì)面臨以下問題:
1)網(wǎng)絡(luò)風(fēng)暴: Master 發(fā)布一次狀態(tài)更新,需要處理大量的網(wǎng)絡(luò)包。如果更新頻繁(例如大量創(chuàng)建索引),Master 的帶寬和 CPU 會(huì)瞬間飽和。
2)收斂慢: 必須等待絕大多數(shù)節(jié)點(diǎn)確認(rèn),集群狀態(tài)才能生效。節(jié)點(diǎn)越多,遇到“慢節(jié)點(diǎn)”拖累整體變更速度的概率就越大。
3)Full GC 風(fēng)險(xiǎn): 大集群通常意味著分片數(shù)巨多。Cluster State 對(duì)象在內(nèi)存中會(huì)變得非常大(幾十 MB 甚至上百 MB)。Master 節(jié)點(diǎn)在處理這個(gè)巨型對(duì)象時(shí),極易發(fā)生 Full GC 導(dǎo)致假死。
4.2 ES更新細(xì)節(jié)
要理解壓力的來(lái)源,必須理解 ES(基于 Lucene)的 “不可變性” (Immutability) 原則。核心機(jī)制:偽更新 (Delete + Insert)
在 ES 內(nèi)部,根本不存在物理意義上的“修改”操作。當(dāng)你執(zhí)行一個(gè) Update 請(qǐng)求時(shí),ES 實(shí)際上在做以下三步:
1.讀取 (Read): 取出舊文檔(如果是 Partial Update,它需要先通過 _source 字段獲取完整文檔)。
2.標(biāo)記刪除 (Soft Delete): 在舊的 Segment(段)文件中,將舊文檔的 ID 標(biāo)記為 .del(邏輯刪除,類似墓碑)。
3.寫入新文檔 (Insert): 將修改后的新文檔作為一個(gè)全新的 Document 寫入到新的 Segment 中,并分配新的 _version 號(hào)。
這意味著,更新不僅僅是 IO 操作,它還涉及大量的 CPU 計(jì)算(重新分詞、重新索引)。
4.3 頻繁更新帶來(lái)的四大壓力:
1、磁盤 I/O 爆炸與 Segment Merge(段合并)風(fēng)暴
?現(xiàn)象: 磁盤 I/O 持續(xù) 100%,寫入拒絕(Rejection)。
?原因: 每次 Update 都會(huì)產(chǎn)生一個(gè)新的小 Segment。ES 后臺(tái)為了優(yōu)化查詢,會(huì)不斷觸發(fā) Segment Merge,將小段合并成大段,并物理剔除被標(biāo)記為 .del 的數(shù)據(jù)。
?壓力點(diǎn): 高頻更新會(huì)導(dǎo)致 Merge 線程極其繁忙,消耗大量的磁盤 IOPS 和 CPU。如果 Merge 速度跟不上產(chǎn)生碎片的速度,ES 會(huì)啟動(dòng) Throttling(寫入限流),導(dǎo)致你的寫入請(qǐng)求被阻塞。
2、查詢性能隨著“墓碑”增加而衰退
?現(xiàn)象: 即使數(shù)據(jù)量看起來(lái)沒變,查詢延遲卻越來(lái)越高。
?原因: 雖然舊文檔被標(biāo)記刪除了,但在物理合并發(fā)生前,它們依然存在于索引中。
?搜索開銷: 查詢時(shí),ES 必須掃描所有文檔(包括舊的),然后在最后階段通過 .del 文件過濾掉已刪除的文檔。如果你的索引中有 50% 是“墓碑”數(shù)據(jù),查詢效率就會(huì)大打折扣。
?BitSet 內(nèi)存占用: 維護(hù)大量的刪除標(biāo)記需要消耗堆內(nèi)存。
3、緩存失效 (Cache Invalidation)
?現(xiàn)象: Filter Cache(Node Query Cache)命中率極低。
?原因: ES 的 Filter Cache 是基于 Segment 的。一旦 Segment 因?yàn)?Merge 發(fā)生了變化,或者產(chǎn)生了新的 Segment,舊的緩存就會(huì)失效。高頻更新導(dǎo)致 Segment 頻繁變動(dòng),緩存根本熱不起來(lái),查詢請(qǐng)求會(huì)直接擊穿到底層磁盤。
4、GC (垃圾回收) 壓力
?原因: Update 過程涉及將舊文檔讀入內(nèi)存、反序列化、修改、再序列化。這會(huì)產(chǎn)生大量的臨時(shí)對(duì)象,增加 JVM 的 Young GC 頻率。如果 Merge 壓力過大導(dǎo)致內(nèi)存堆積,甚至可能觸發(fā) Old GC 或 Full GC,導(dǎo)致節(jié)點(diǎn) "Stop-the-World"。
審核編輯 黃宇
-
京東
+關(guān)注
關(guān)注
2文章
1118瀏覽量
50111
發(fā)布評(píng)論請(qǐng)先 登錄
RAG(檢索增強(qiáng)生成)原理與實(shí)踐
京東訂單API:批量訂單處理,效率倍增!
低溫?zé)o壓燒結(jié)銀的前世今生:從發(fā)明到未來(lái)趨勢(shì)
1688交易API:B2B訂單自動(dòng)化,加速成交!
解碼助聽器 B 端合作的 “靠譜密碼”
京東訂單API:自動(dòng)化處理訂單,提升物流效率!
偉創(chuàng)力珠海B11工廠完成SMT端到端示范驗(yàn)證
芯片裝甲的前世今生
助聽器源頭廠家新選擇:旋音科技憑三大服務(wù)優(yōu)勢(shì)賦能 B 端運(yùn)營(yíng)
旋音科技助聽器廠家:破解 B 端合作難題,以服務(wù)優(yōu)勢(shì)構(gòu)建競(jìng)爭(zhēng)壁壘
PoP疊層封裝與光電路組裝技術(shù)解析
蔚來(lái)端到端模型化架構(gòu)如何大幅提升安全上限
京東 API 接口:打造高效京東店鋪訂單處理系統(tǒng)
京東API集成訂單系統(tǒng),處理速度提升50%!
一文帶你厘清自動(dòng)駕駛端到端架構(gòu)差異
POP訂單B端檢索系統(tǒng)架構(gòu)的前世今生
評(píng)論