日均5億查詢量的京東訂單中心,為什么舍MySQL用ES?

來源:京東技術訂閱號(ID:jingdongjishu)

京東到家訂單中心系統(tǒng)業(yè)務中雏赦,無論是外部商家的訂單生產(chǎn)劫笙,或是內(nèi)部上下游系統(tǒng)的依賴,訂單查詢的調(diào)用量都非常大星岗,造成了訂單數(shù)據(jù)讀多寫少的情況填大。我們把訂單數(shù)據(jù)存儲在MySQL中,但顯然只通過DB來支撐大量的查詢是不可取的俏橘。同時對于一些復雜的查詢允华,MySQL支持得不夠友好,所以訂單中心系統(tǒng)使用了Elasticsearch來承載訂單查詢的主要壓力寥掐。

image

Elasticsearch作為一款功能強大的分布式搜索引擎靴寂,支持近實時的存儲、搜索數(shù)據(jù)召耘,在京東到家訂單系統(tǒng)中發(fā)揮著巨大作用百炬,目前訂單中心ES集群存儲數(shù)據(jù)量達到10億個文檔,日均查詢量達到5億污它。
隨著京東到家近幾年業(yè)務的快速發(fā)展剖踊,訂單中心ES架設方案也不斷演進,發(fā)展至今ES集群架設是一套實時互備方案轨蛤,很好地保障了ES集群讀寫的穩(wěn)定性蜜宪,下面就給大家介紹一下這個歷程以及過程中遇到的一些坑。

ES 集群架構演進之路

1祥山、初始階段
訂單中心ES初始階段如一張白紙圃验,架設方案基本沒有,很多配置都是保持集群默認配置缝呕。整個集群部署在集團的彈性云上澳窑,ES集群的節(jié)點以及機器部署都比較混亂。同時按照集群維度來看供常,一個ES集群會有單點問題摊聋,顯然對于訂單中心業(yè)務來說也是不被允許的。2栈暇、集群隔離階段和很多業(yè)務一樣麻裁,ES集群采用的混布的方式。但由于訂單中心ES存儲的是線上訂單數(shù)據(jù),偶爾會發(fā)生混布集群搶占系統(tǒng)大量資源煎源,導致整個訂單中心ES服務異常色迂。顯然任何影響到訂單查詢穩(wěn)定性的情況都是無法容忍的,所以針對于這個情況手销,先是對訂單中心ES所在的彈性云歇僧,遷出那些系統(tǒng)資源搶占很高的集群節(jié)點,ES集群狀況稍有好轉(zhuǎn)锋拖。但隨著集群數(shù)據(jù)不斷增加诈悍,彈性云配置已經(jīng)不太能滿足ES集群,且為了完全的物理隔離兽埃,最終干脆將訂單中心ES集群部署到高配置的物理機上侥钳,ES集群性能又得到提升。3讲仰、節(jié)點副本調(diào)優(yōu)階段ES的性能跟硬件資源有很大關系慕趴,當ES集群單獨部署到物理機器上時,集群內(nèi)部的節(jié)點并不是獨占整臺物理機資源鄙陡,在集群運行的時候同一物理機上的節(jié)點仍會出現(xiàn)資源搶占的問題。所以在這種情況下躏啰,為了讓ES單個節(jié)點能夠使用最大程度的機器資源趁矾,采用每個ES節(jié)點部署在單獨一臺物理機上方式。但緊接著给僵,問題又來了匹耕,如果單個節(jié)點出現(xiàn)瓶頸了呢沼瘫?我們應該怎么再優(yōu)化呢?ES查詢的原理,當請求打到某號分片的時候缆娃,如果沒有指定分片類型(Preference參數(shù))查詢,請求會負載到對應分片號的各個節(jié)點上岸晦。而集群默認副本配置是一主一副三热,針對此情況,我們想到了擴容副本的方式脯爪,由默認的一主一副變?yōu)橐恢鞫痹虮保瑫r增加相應物理機。

image

訂單中心ES集群架設示意圖
如圖痕慢,整個架設方式通過VIP來負載均衡外部請求:整個集群有一套主分片尚揣,二套副分片(一主二副),從網(wǎng)關節(jié)點轉(zhuǎn)發(fā)過來的請求掖举,會在打到數(shù)據(jù)節(jié)點之前通過輪詢的方式進行均衡快骗。集群增加一套副本并擴容機器的方式,增加了集群吞吐量,從而提升了整個集群查詢性能方篮。下圖為訂單中心ES集群各階段性能示意圖名秀,直觀地展示了各階段優(yōu)化后ES集群性能的顯著提升:

image
當然分片數(shù)量和分片副本數(shù)量并不是越多越好,在此階段恭取,我們對選擇適當?shù)姆制瑪?shù)量做了進一步探索泰偿。分片數(shù)可以理解為MySQL中的分庫分表,而當前訂單中心ES查詢主要分為兩類:單ID查詢以及分頁查詢蜈垮。
分片數(shù)越大耗跛,集群橫向擴容規(guī)模也更大,根據(jù)分片路由的單ID查詢吞吐量也能大大提升攒发,但聚合的分頁查詢性能則將降低调塌;分片數(shù)越小,集群橫向擴容規(guī)模也更小惠猿,單ID的查詢性能也會下降羔砾,但分頁查詢的性能將會提升。所以如何均衡分片數(shù)量和現(xiàn)有查詢業(yè)務偶妖,我們做了很多次調(diào)整壓測姜凄,最終選擇了集群性能較好的分片數(shù)。4趾访、主從集群調(diào)整階段到此态秧,訂單中心的ES集群已經(jīng)初具規(guī)模,但由于訂單中心業(yè)務時效性要求高扼鞋,對ES查詢穩(wěn)定性要求也高申鱼,如果集群中有節(jié)點發(fā)生異常,查詢服務會受到影響云头,從而影響到整個訂單生產(chǎn)流程捐友。很明顯這種異常情況是致命的,所以為了應對這種情況溃槐,我們初步設想是增加一個備用集群匣砖,當主集群發(fā)生異常時,可以實時的將查詢流量降級到備用集群竿痰。那備用集群應該怎么來搭脆粥?主備之間數(shù)據(jù)如何同步?備用集群應該存儲什么樣的數(shù)據(jù)影涉?考慮到ES集群暫時沒有很好的主備方案变隔,同時為了更好地控制ES數(shù)據(jù)寫入,我們采用業(yè)務雙寫的方式來搭設主備集群蟹倾。每次業(yè)務操作需要寫入ES數(shù)據(jù)時匣缘,同步寫入主集群數(shù)據(jù)猖闪,然后異步寫入備集群數(shù)據(jù)。同時由于大部分ES查詢的流量都來源于近幾天的訂單肌厨,且訂單中心數(shù)據(jù)庫數(shù)據(jù)已有一套歸檔機制培慌,將指定天數(shù)之前已經(jīng)關閉的訂單轉(zhuǎn)移到歷史訂單庫。所以歸檔機制中增加刪除備集群文檔的邏輯柑爸,讓新搭建的備集群存儲的訂單數(shù)據(jù)與訂單中心線上數(shù)據(jù)庫中的數(shù)據(jù)量保持一致吵护。同時使用ZK在查詢服務中做了流量控制開關,保證查詢流量能夠?qū)崟r降級到備集群表鳍。在此馅而,訂單中心主從集群完成,ES查詢服務穩(wěn)定性大大提升譬圣。
image
5瓮恭、現(xiàn)今:****實時互備雙集群階段期間由于主集群ES版本是較低的1.7,而現(xiàn)今ES穩(wěn)定版本都已經(jīng)迭代到6.x厘熟,新版本的ES不僅性能方面優(yōu)化很大屯蹦,更提供了一些新的好用的功能,所以我們對主集群進行了一次版本升級绳姨,直接從原來的1.7升級到6.x版本登澜。集群升級的過程繁瑣而漫長,不但需要保證線上業(yè)務無任何影響飘庄,平滑無感知升級帖渠,同時由于ES集群暫不支持從1.7到6.x跨越多個版本的數(shù)據(jù)遷移,所以需要通過重建索引的方式來升級主集群竭宰,具體升級過程就不在此贅述了。主集群升級的時候必不可免地會發(fā)生不可用的情況份招,但對于訂單中心ES查詢服務切揭,這種情況是不允許的。所以在升級的階段中锁摔,備集群暫時頂上充當主集群廓旬,來支撐所有的線上ES查詢,保證升級過程不影響正常線上服務谐腰。同時針對于線上業(yè)務孕豹,我們對兩個集群做了重新的規(guī)劃定義,承擔的線上查詢流量也做了重新的劃分十气。備集群存儲的是線上近幾天的熱點數(shù)據(jù)励背,數(shù)據(jù)規(guī)模遠小于主集群,大約是主集群文檔數(shù)的十分之一砸西。集群數(shù)據(jù)量小叶眉,在相同的集群部署規(guī)模下址儒,備集群的性能要優(yōu)于主集群。然而在線上真實場景中衅疙,線上大部分查詢流量也來源于熱點數(shù)據(jù)莲趣,所以用備集群來承載這些熱點數(shù)據(jù)的查詢,而備集群也慢慢演變成一個熱數(shù)據(jù)集群饱溢。之前的主集群存儲的是全量數(shù)據(jù)喧伞,用該集群來支撐剩余較小部分的查詢流量,這部分查詢主要是需要搜索全量訂單的特殊場景查詢以及訂單中心系統(tǒng)內(nèi)部查詢等绩郎,而主集群也慢慢演變成一個冷數(shù)據(jù)集群潘鲫。同時備集群增加一鍵降級到主集群的功能,兩個集群地位同等重要嗽上,但都可以各自降級到另一個集群次舌。雙寫策略也優(yōu)化為:假設有AB集群,正常同步方式寫主(A集群)異步方式寫備(B集群)兽愤。A集群發(fā)生異常時彼念,同步寫B(tài)集群(主),異步寫A集群(備)浅萧。
image

ES 訂單數(shù)據(jù)的同步方案

MySQL數(shù)據(jù)同步到ES中逐沙,大致總結(jié)可以分為兩種方案:

  • 方案1:監(jiān)聽MySQL的Binlog,分析Binlog將數(shù)據(jù)同步到ES集群中洼畅。
  • 方案2:直接通過ES API將數(shù)據(jù)寫入到ES集群中吩案。

考慮到訂單系統(tǒng)ES服務的業(yè)務特殊性,對于訂單數(shù)據(jù)的實時性較高帝簇,顯然監(jiān)聽Binlog的方式相當于異步同步徘郭,有可能會產(chǎn)生較大的延時性。且方案1實質(zhì)上跟方案2類似丧肴,但又引入了新的系統(tǒng)残揉,維護成本也增高。所以訂單中心ES采用了直接通過ES API寫入訂單數(shù)據(jù)的方式芋浮,該方式簡潔靈活抱环,能夠很好的滿足訂單中心數(shù)據(jù)同步到ES的需求。由于ES訂單數(shù)據(jù)的同步采用的是在業(yè)務中寫入的方式纸巷,當新建或更新文檔發(fā)生異常時镇草,如果重試勢必會影響業(yè)務正常操作的響應時間。所以每次業(yè)務操作只更新一次ES瘤旨,如果發(fā)生錯誤或者異常梯啤,在數(shù)據(jù)庫中插入一條補救任務,有Worker任務會實時地掃這些數(shù)據(jù)裆站,以數(shù)據(jù)庫訂單數(shù)據(jù)為基準來再次更新ES數(shù)據(jù)条辟。通過此種補償機制黔夭,來保證ES數(shù)據(jù)與數(shù)據(jù)庫訂單數(shù)據(jù)的最終一致性。

遇到的一些坑

1羽嫡、實時性要求高的查詢走DB對于ES寫入機制的有了解的同學可能會知道本姥,新增的文檔會被收集到Indexing Buffer,然后寫入到文件系統(tǒng)緩存中杭棵,到了文件系統(tǒng)緩存中就可以像其他的文件一樣被索引到婚惫。然而默認情況文檔從Indexing Buffer到文件系統(tǒng)緩存(即Refresh操作)是每秒分片自動刷新,所以這就是我們說ES是近實時搜索而非實時的原因:文檔的變化并不是立即對搜索可見魂爪,但會在一秒之內(nèi)變?yōu)榭梢娤认稀.斍坝唵蜗到y(tǒng)ES采用的是默認Refresh配置,故對于那些訂單數(shù)據(jù)實時性比較高的業(yè)務滓侍,直接走數(shù)據(jù)庫查詢蒋川,保證數(shù)據(jù)的準確性。

image

2撩笆、避免深分頁查詢ES集群的分頁查詢支持from和size參數(shù)捺球,查詢的時候,每個分片必須構造一個長度為from+size的優(yōu)先隊列夕冲,然后回傳到網(wǎng)關節(jié)點氮兵,網(wǎng)關節(jié)點再對這些優(yōu)先隊列進行排序找到正確的size個文檔。假設在一個有6個主分片的索引中歹鱼,from為10000泣栈,size為10,每個分片必須產(chǎn)生10010個結(jié)果弥姻,在網(wǎng)關節(jié)點中匯聚合并60060個結(jié)果南片,最終找到符合要求的10個文檔。由此可見庭敦,當from足夠大的時候铃绒,就算不發(fā)生OOM,也會影響到CPU和帶寬等螺捐,從而影響到整個集群的性能。所以應該避免深分頁查詢矮燎,盡量不去使用定血。3、FieldData與Doc Values****FieldData線上查詢出現(xiàn)偶爾超時的情況诞外,通過調(diào)試查詢語句澜沟,定位到是跟排序有關系。排序在es1.x版本使用的是FieldData結(jié)構峡谊,F(xiàn)ieldData占用的是JVM Heap內(nèi)存茫虽,JVM內(nèi)存是有限刊苍,對于FieldData Cache會設定一個閾值。如果空間不足時濒析,使用最久未使用(LRU)算法移除FieldData正什,同時加載新的FieldData Cache,加載的過程需要消耗系統(tǒng)資源号杏,且耗時很大婴氮。所以導致這個查詢的響應時間暴漲,甚至影響整個集群的性能盾致。針對這種問題主经,解決方式是采用Doc Values。Doc ValuesDoc Values是一種列式的數(shù)據(jù)存儲結(jié)構庭惜,跟FieldData很類似罩驻,但其存儲位置是在Lucene文件中,即不會占用JVM Heap护赊。隨著ES版本的迭代惠遏,Doc Values比FieldData更加穩(wěn)定,Doc Values在2.x起為默認設置百揭。

總結(jié)

架構的快速迭代源于業(yè)務的快速發(fā)展爽哎,正是由于近幾年到家業(yè)務的高速發(fā)展,訂單中心的架構也不斷優(yōu)化升級器一。而架構方案沒有最好的课锌,只有最合適的,相信再過幾年祈秕,訂單中心的架構又將是另一個面貌渺贤,但吞吐量更大,性能更好请毛,穩(wěn)定性更強志鞍,將是訂單中心系統(tǒng)永遠的追求。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末方仿,一起剝皮案震驚了整個濱河市固棚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌仙蚜,老刑警劉巖此洲,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異委粉,居然都是意外死亡呜师,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門贾节,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汁汗,“玉大人衷畦,你說我怎么就攤上這事≈疲” “怎么了祈争?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長送爸。 經(jīng)常有香客問我铛嘱,道長,這世上最難降的妖魔是什么袭厂? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任墨吓,我火速辦了婚禮,結(jié)果婚禮上纹磺,老公的妹妹穿的比我還像新娘帖烘。我一直安慰自己,他們只是感情好橄杨,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布秘症。 她就那樣靜靜地躺著,像睡著了一般式矫。 火紅的嫁衣襯著肌膚如雪乡摹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天采转,我揣著相機與錄音聪廉,去河邊找鬼。 笑死故慈,一個胖子當著我的面吹牛板熊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播察绷,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼干签,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拆撼?” 一聲冷哼從身側(cè)響起容劳,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闸度,沒想到半個月后鸭蛙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡筋岛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了晒哄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睁宰。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡肪获,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出柒傻,到底是詐尸還是另有隱情孝赫,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布红符,位于F島的核電站青柄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏预侯。R本人自食惡果不足惜致开,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望萎馅。 院中可真熱鬧双戳,春花似錦、人聲如沸糜芳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽峭竣。三九已至塘辅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間皆撩,已是汗流浹背扣墩。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留毅访,地道東北人沮榜。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像喻粹,于是被迫代替她去往敵國和親蟆融。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容