美团外卖订单中心的演进
【前言】[轉(zhuǎn):http://geek.csdn.net/news/detail/101994]
美團(tuán)外賣從2013年9月成交第一單以來(lái),已走過(guò)了三個(gè)年頭。期間,業(yè)務(wù)飛速發(fā)展,美團(tuán)外賣由日均幾單發(fā)展為日均500萬(wàn)單(9月11日已突破600萬(wàn))的大型O2O互聯(lián)網(wǎng)外賣服務(wù)平臺(tái)。平臺(tái)支持的品類也由最初外賣單品拓展為全品類。
隨著訂單量的增長(zhǎng)、業(yè)務(wù)復(fù)雜度的提升,外賣訂單系統(tǒng)也在不斷演變進(jìn)化,從早期一個(gè)訂單業(yè)務(wù)模塊到現(xiàn)在分布式可擴(kuò)展的高性能、高可用、高穩(wěn)定訂單系統(tǒng)。整個(gè)發(fā)展過(guò)程中,訂單系統(tǒng)經(jīng)歷了幾個(gè)明顯的階段,下面本篇文章將為大家介紹一下訂單系統(tǒng)的演進(jìn)過(guò)程,重點(diǎn)關(guān)注各階段的業(yè)務(wù)特征、挑戰(zhàn)及應(yīng)對(duì)之道。
為方便大家更好地了解整個(gè)演進(jìn)過(guò)程,我們首先看一下外賣業(yè)務(wù)。
外賣訂單業(yè)務(wù)
外賣訂單業(yè)務(wù)是一個(gè)需要即時(shí)送的業(yè)務(wù),對(duì)實(shí)時(shí)性要求很高。從用戶訂餐到最終送達(dá)用戶,一般在1小時(shí)內(nèi)。如果最終送達(dá)用戶時(shí)間變長(zhǎng),會(huì)帶來(lái)槽糕的用戶體驗(yàn)。在1小時(shí)內(nèi),訂單會(huì)快速經(jīng)過(guò)多個(gè)階段,直到最終送達(dá)用戶。各個(gè)階段需要緊密配合,確保訂單順利完成。
下圖是一個(gè)用戶視角的訂單流程圖:
從普通用戶的角度來(lái)看,一個(gè)外賣訂單從下單后,會(huì)經(jīng)歷支付、商家接單、配送、用戶收貨、售后及訂單完成多個(gè)階段。以技術(shù)的視角來(lái)分解的話,每個(gè)階段依賴于多個(gè)子服務(wù)來(lái)共同完成,比如下單會(huì)依賴于購(gòu)物車、訂單預(yù)覽、確認(rèn)訂單服務(wù),這些子服務(wù)又會(huì)依賴于底層基礎(chǔ)系統(tǒng)來(lái)完成其功能。
外賣業(yè)務(wù)另一個(gè)重要特征是一天內(nèi)訂單量會(huì)規(guī)律變化,訂單會(huì)集中在中午、晚上兩個(gè)“飯點(diǎn)”附近,而其它時(shí)間的訂單量較少。這樣,飯點(diǎn)附近系統(tǒng)壓力會(huì)相對(duì)較大。
下圖是一天內(nèi)的外賣訂單量分布圖:
總結(jié)而言,外賣業(yè)務(wù)具有如下特征:
流程較長(zhǎng)且實(shí)時(shí)性要求高;
訂單量高且集中。
下面將按時(shí)間脈絡(luò)為大家講解訂單系統(tǒng)經(jīng)歷的各個(gè)階段、各階段業(yè)務(wù)特征、挑戰(zhàn)以及應(yīng)對(duì)之道。
訂單系統(tǒng)雛型
外賣業(yè)務(wù)發(fā)展早期,第一目標(biāo)是要能夠快速驗(yàn)證業(yè)務(wù)的可行性。技術(shù)上,我們需要保證架構(gòu)足夠靈活、快速迭代從而滿足業(yè)務(wù)快速試錯(cuò)的需求。
在這個(gè)階段,我們將訂單相關(guān)功能組織成模塊,與其它模塊(門店模塊等)一起形成公用jar包,然后各個(gè)系統(tǒng)通過(guò)引入jar包來(lái)使用訂單功能。
早期系統(tǒng)的整體架構(gòu)圖如下所示:
早期,外賣整體架構(gòu)簡(jiǎn)單、靈活,公共業(yè)務(wù)邏輯通過(guò)jar包實(shí)現(xiàn)后集成到各端應(yīng)用,應(yīng)用開(kāi)發(fā)部署相對(duì)簡(jiǎn)單。比較適合業(yè)務(wù)早期邏輯簡(jiǎn)單、業(yè)務(wù)量較小、需要快速迭代的情況。但是,隨著業(yè)務(wù)邏輯的復(fù)雜、業(yè)務(wù)量的增長(zhǎng),單應(yīng)用架構(gòu)的弊端逐步暴露出來(lái)。系統(tǒng)復(fù)雜后,大家共用一個(gè)大項(xiàng)目進(jìn)行開(kāi)發(fā)部署,協(xié)調(diào)的成本變高;業(yè)務(wù)之間相互影響的問(wèn)題也逐漸增多。
早期業(yè)務(wù)處于不斷試錯(cuò)、快速變化、快速迭代階段,通過(guò)上述架構(gòu),我們能緊跟業(yè)務(wù),快速滿足業(yè)務(wù)需求。隨著業(yè)務(wù)的發(fā)展以及業(yè)務(wù)的逐步成熟,我們對(duì)系統(tǒng)進(jìn)行逐步升級(jí),從而更好地支持業(yè)務(wù)。
獨(dú)立的訂單系統(tǒng)
2014年4月,外賣訂單量達(dá)到了10萬(wàn)單/日,而且訂單量還在持續(xù)增長(zhǎng)。這時(shí)候,業(yè)務(wù)大框架基本成型,業(yè)務(wù)在大框架基礎(chǔ)上快速迭代。大家共用一個(gè)大項(xiàng)目進(jìn)行開(kāi)發(fā)部署,相互影響,協(xié)調(diào)成本變高;多個(gè)業(yè)務(wù)部署于同一VM,相互影響的情況也在增多。
為解決開(kāi)發(fā)、部署、運(yùn)行時(shí)相互影響的問(wèn)題。我們將訂單系統(tǒng)進(jìn)行獨(dú)立拆分,從而獨(dú)立開(kāi)發(fā)、部署、運(yùn)行,避免受其它業(yè)務(wù)影響。
系統(tǒng)拆分主要有如下幾個(gè)原則:
相關(guān)業(yè)務(wù)拆分獨(dú)立系統(tǒng);
優(yōu)先級(jí)一致的業(yè)務(wù)拆分獨(dú)立系統(tǒng);
拆分系統(tǒng)包括業(yè)務(wù)服務(wù)和數(shù)據(jù)。
基于以上原則,我們將訂單系統(tǒng)進(jìn)行獨(dú)立拆分,所有訂單服務(wù)通過(guò)RPC接口提供給外部使用。訂單系統(tǒng)內(nèi)部,我們將功能按優(yōu)先級(jí)拆分為不同子系統(tǒng),避免相互影響。訂單系統(tǒng)通過(guò)MQ(隊(duì)列)消息,通知外部訂單狀態(tài)變更。
獨(dú)立拆分后的訂單系統(tǒng)架構(gòu)如下所示:
其中,最底層是數(shù)據(jù)存儲(chǔ)層,訂單相關(guān)數(shù)據(jù)獨(dú)立存儲(chǔ)。訂單服務(wù)層,我們按照優(yōu)先級(jí)將訂單服務(wù)劃分為三個(gè)系統(tǒng),分別為交易系統(tǒng)、查詢系統(tǒng)、異步處理系統(tǒng)。
獨(dú)立拆分后,可以避免業(yè)務(wù)間的相互影響。快速支持業(yè)務(wù)迭代需求的同時(shí),保障系統(tǒng)穩(wěn)定性。
高性能、高可用、高穩(wěn)定的訂單系統(tǒng)
訂單系統(tǒng)經(jīng)過(guò)上述獨(dú)立拆分后,有效地避免了業(yè)務(wù)間的相互干擾,保障迭代速度的同時(shí),保證了系統(tǒng)穩(wěn)定性。這時(shí),我們的訂單量突破百萬(wàn),而且還在持續(xù)增長(zhǎng)。之前的一些小問(wèn)題,在訂單量增加后,被放大,進(jìn)而影響用戶體驗(yàn)。比如,用戶支付成功后,極端情況下(比如網(wǎng)絡(luò)、數(shù)據(jù)庫(kù)問(wèn)題)會(huì)導(dǎo)致支付成功消息處理失敗,用戶支付成功后依然顯示未支付。訂單量變大后,問(wèn)題訂單相應(yīng)增多。我們需要提高系統(tǒng)的可靠性,保證訂單功能穩(wěn)定可用。
另外,隨著訂單量的增長(zhǎng)、訂單業(yè)務(wù)的復(fù)雜,對(duì)訂單系統(tǒng)的性能、穩(wěn)定性、可用性等提出了更高的要求。
為了提供更加穩(wěn)定、可靠的訂單服務(wù),我們對(duì)拆分后的訂單系統(tǒng)進(jìn)行進(jìn)一步升級(jí)。下面將分別介紹升級(jí)涉及的主要內(nèi)容。
性能優(yōu)化
系統(tǒng)獨(dú)立拆分后,可以方便地對(duì)訂單系統(tǒng)進(jìn)行優(yōu)化升級(jí)。我們對(duì)獨(dú)立拆分后的訂單系統(tǒng)進(jìn)行了很多的性能優(yōu)化工作,提升服務(wù)整體性能,優(yōu)化工作主要涉及如下幾個(gè)方面。
異步化
服務(wù)所需要處理的工作越少,其性能自然越高。可以通過(guò)將部分操作異步化來(lái)減少需要同步進(jìn)行的操作,進(jìn)而提升服務(wù)的性能。異步化有兩種方案。
線程或線程池:將異步操作放在單獨(dú)線程中處理,避免阻塞服務(wù)線程;
消息異步:異步操作通過(guò)接收消息完成。
異步化帶來(lái)一個(gè)隱患,如何保障異步操作的執(zhí)行。這個(gè)場(chǎng)景主要發(fā)生在應(yīng)用重啟時(shí),對(duì)于通過(guò)線程或線程池進(jìn)行的異步化,JVM重啟時(shí),后臺(tái)執(zhí)行的異步操作可能尚未完成。這時(shí),需要通過(guò)JVM優(yōu)雅關(guān)閉來(lái)保證異步操作進(jìn)行完成后,JVM再關(guān)閉。通過(guò)消息來(lái)進(jìn)行的,消息本身已提供持久化,不受應(yīng)用重啟影響。
具體到訂單系統(tǒng),我們通過(guò)將部分不必同步進(jìn)行的操作異步化,來(lái)提升對(duì)外服務(wù)接口的性能。不需要立即生效的操作即可以異步進(jìn)行,比如發(fā)放紅包、PUSH推送、統(tǒng)計(jì)等。
以訂單配送PUSH推送為例,將PUSH推送異步化后的處理流程變更如下所示:
PUSH異步化后,線程#1在更新訂單狀態(tài)、發(fā)送消息后立即返回,而不用同步等待PUSH推送完成。而PUSH推送異步在線程#2中完成。
并行化
操作并行化也是提升性能的一大利器,并行化將原本串行的工作并行執(zhí)行,降低整體處理時(shí)間。我們對(duì)所有訂單服務(wù)進(jìn)行分析,將其中非相互依賴的操作并行化,從而提升整體的響應(yīng)時(shí)間。
以用戶下單為例,第一步是從各個(gè)依賴服務(wù)獲取信息,包括門店、菜品、用戶信息等。獲取這些信息并不需要相互依賴,故可以將其并行化,并行后的處理流程變更如下所示:
通過(guò)將獲取信息并行化,可有效縮短下單時(shí)間,提升下單接口性能。
緩存
通過(guò)將統(tǒng)計(jì)信息進(jìn)行提前計(jì)算后緩存,避免獲取數(shù)據(jù)時(shí)進(jìn)行實(shí)時(shí)計(jì)算,從而提升獲取統(tǒng)計(jì)數(shù)據(jù)的服務(wù)性能。比如對(duì)于首單、用戶已減免配送費(fèi)等,通過(guò)提前計(jì)算后緩存,可以簡(jiǎn)化實(shí)時(shí)獲取數(shù)據(jù)邏輯,節(jié)約時(shí)間。
以用戶已減免配送費(fèi)為例,如果需要實(shí)時(shí)計(jì)算,則需要取到用戶所有訂單后,再進(jìn)行計(jì)算,這樣實(shí)時(shí)計(jì)算成本較高。我們通過(guò)提前計(jì)算,緩存用戶已減免配送費(fèi)。需要取用戶已減免配送費(fèi)時(shí),從緩存中取即可,不必實(shí)時(shí)計(jì)算。具體來(lái)說(shuō),包括如下幾點(diǎn):
通過(guò)緩存保存用戶已減免配送費(fèi);
用戶下單時(shí),如果訂單有減免配送費(fèi),增加緩存中用戶減免配送費(fèi)金額(異步進(jìn)行);
訂單取消時(shí),如果訂單有減免配送費(fèi),減少緩存中用戶減免配送費(fèi)金額(異步進(jìn)行)。
一致性優(yōu)化
訂單系統(tǒng)涉及交易,需要保證數(shù)據(jù)的一致性。否則,一旦出現(xiàn)問(wèn)題,可能會(huì)導(dǎo)致訂單不能及時(shí)配送、交易金額不對(duì)等。
交易一個(gè)很重要的特征是其操作具有事務(wù)性,訂單系統(tǒng)是一個(gè)復(fù)雜的分布式系統(tǒng),比如支付涉及訂單系統(tǒng)、支付平臺(tái)、支付寶/網(wǎng)銀等第三方。僅通過(guò)傳統(tǒng)的數(shù)據(jù)庫(kù)事務(wù)來(lái)保障不太可行。對(duì)于訂單交易系統(tǒng)的事務(wù)性,并不要求嚴(yán)格滿足傳統(tǒng)數(shù)據(jù)庫(kù)事務(wù)的ACID性質(zhì),只需要最終結(jié)果一致即可。針對(duì)訂單系統(tǒng)的特征,我們通過(guò)如下種方式來(lái)保障最終結(jié)果的一致性。
重試/冪等
通過(guò)延時(shí)重試,保證操作最終會(huì)最執(zhí)行。比如退款操作,如退款時(shí)遇到網(wǎng)絡(luò)或支付平臺(tái)故障等問(wèn)題,會(huì)延時(shí)進(jìn)行重試,保證退款最終會(huì)被完成。重試又會(huì)帶來(lái)另一個(gè)問(wèn)題,即部分操作重復(fù)進(jìn)行,需要對(duì)操作進(jìn)行冪等處理,保證重試的正確性。
以退款操作為例,加入重試/冪等后的處理流程如下所示:
退款操作首先會(huì)檢查是否已經(jīng)退款,如果已經(jīng)退款,直接返回。否則,向支付平臺(tái)發(fā)起退款,從而保證操作冪等,避免重復(fù)操作帶來(lái)問(wèn)題。如果發(fā)起退款失敗(比如網(wǎng)絡(luò)或支付平臺(tái)故障),會(huì)將任務(wù)放入延時(shí)隊(duì)列,稍后重試。否則,直接返回。
通過(guò)重試+冪等,可以保證退款操作最終一定會(huì)完成。
2PC
2PC是指分布式事務(wù)的兩階段提交,通過(guò)2PC來(lái)保證多個(gè)系統(tǒng)的數(shù)據(jù)一致性。比如下單過(guò)程中,涉及庫(kù)存、優(yōu)惠資格等多個(gè)資源,下單時(shí)會(huì)首先預(yù)占資源(對(duì)應(yīng)2PC的第一階段),下單失敗后會(huì)釋放資源(對(duì)應(yīng)2PC的回滾階段),成功后會(huì)使用資源(對(duì)應(yīng)2PC的提交階段)。對(duì)于2PC,網(wǎng)上有大量的說(shuō)明,這里不再繼續(xù)展開(kāi)。
高可用
分布式系統(tǒng)的可用性由其各個(gè)組件的可用性共同決定,要提升分布式系統(tǒng)的可用性,需要綜合提升組成分布式系統(tǒng)的各個(gè)組件的可用性。
針對(duì)訂單系統(tǒng)而言,其主要組成組件包括三類:存儲(chǔ)層、中間件層、服務(wù)層。下面將分層說(shuō)明訂單系統(tǒng)的可用性。
存儲(chǔ)層
存儲(chǔ)層的組件如MySQL、ES等本身已經(jīng)實(shí)現(xiàn)了高可用,比如MySQL通過(guò)主從集群、ES通過(guò)分片復(fù)制來(lái)實(shí)現(xiàn)高可用。存儲(chǔ)層的高可用依賴各個(gè)存儲(chǔ)組件即可。
中間件層
分布式系統(tǒng)會(huì)大量用到各類中間件,比如服務(wù)調(diào)用框架等,這類中間件一般使用開(kāi)源產(chǎn)品或由公司基礎(chǔ)平臺(tái)提供,本身已具備高可用。
服務(wù)層
在分布式系統(tǒng)中,服務(wù)間通過(guò)相互調(diào)用來(lái)完成業(yè)務(wù)功能,一旦某個(gè)服務(wù)出現(xiàn)問(wèn)題,會(huì)級(jí)聯(lián)影響調(diào)用方服務(wù),進(jìn)而導(dǎo)致系統(tǒng)崩潰。分布式系統(tǒng)中的依賴容災(zāi)是影響服務(wù)高可用的一個(gè)重要方面。
依賴容災(zāi)主要有如下幾個(gè)思路:
依賴超時(shí)設(shè)置;
依賴災(zāi)備;
依賴降級(jí);
限制依賴使用資源。
訂單系統(tǒng)會(huì)依賴多個(gè)其它服務(wù),也存在這個(gè)問(wèn)題。當(dāng)前訂單系統(tǒng)通過(guò)同時(shí)采用上述四種方法,來(lái)避免底層服務(wù)出現(xiàn)問(wèn)題時(shí),影響整體服務(wù)。具體實(shí)現(xiàn)上,我們采用Hystrix框架來(lái)完成依賴容災(zāi)功能。Hystrix框架采用上述四種方法,有效實(shí)現(xiàn)依賴容災(zāi)。訂單系統(tǒng)依賴容災(zāi)示意圖如下所示:
通過(guò)為每個(gè)依賴服務(wù)設(shè)置獨(dú)立的線程池、合理的超時(shí)時(shí)間及出錯(cuò)時(shí)回退方法,有效避免服務(wù)出現(xiàn)問(wèn)題時(shí),級(jí)聯(lián)影響,導(dǎo)致整體服務(wù)不可用,從而實(shí)現(xiàn)服務(wù)高可用。
另外,訂單系統(tǒng)服務(wù)層都是無(wú)狀態(tài)服務(wù),通過(guò)集群+多機(jī)房部署,可以避免單點(diǎn)問(wèn)題及機(jī)房故障,實(shí)現(xiàn)高可用。
小結(jié)
上面都是通過(guò)架構(gòu)、技術(shù)實(shí)現(xiàn)層面來(lái)保障訂單系統(tǒng)的性能、穩(wěn)定性、可用性。實(shí)際中,有很多的事故是人為原因?qū)е碌模撕玫募軜?gòu)、技術(shù)實(shí)現(xiàn)外,通過(guò)規(guī)范、制度來(lái)規(guī)避人為事故也是保障性能、穩(wěn)定性、可用性的重要方面。訂單系統(tǒng)通過(guò)完善需求review、方案評(píng)審、代碼review、測(cè)試上線、后續(xù)跟進(jìn)流程來(lái)避免人為因素影響訂單系統(tǒng)穩(wěn)定性。
通過(guò)以上措施,我們將訂單系統(tǒng)建設(shè)成了一個(gè)高性能、高穩(wěn)定、高可用的分布式系統(tǒng)。其中,交易系統(tǒng)tp99為150ms、查詢系統(tǒng)tp99時(shí)間為40ms。整體系統(tǒng)可用性為6個(gè)9。
可擴(kuò)展的訂單系統(tǒng)
訂單系統(tǒng)經(jīng)過(guò)上面介紹的整體升級(jí)后,已經(jīng)是一個(gè)高性能、高穩(wěn)定、高可用的分布式系統(tǒng)。但是系統(tǒng)的的可擴(kuò)展性還存在一定問(wèn)題,部分服務(wù)只能通過(guò)垂直擴(kuò)展(增加服務(wù)器配置)而不能通過(guò)水平擴(kuò)展(加機(jī)器)來(lái)進(jìn)行擴(kuò)容。但是,服務(wù)器配置有上限,導(dǎo)致服務(wù)整體容量受到限制。
到2015年5月的時(shí)候,這個(gè)問(wèn)題就比較突出了。當(dāng)時(shí),數(shù)據(jù)庫(kù)服務(wù)器寫接近單機(jī)上限。業(yè)務(wù)預(yù)期還會(huì)繼續(xù)快速增長(zhǎng)。為保障業(yè)務(wù)的快速增長(zhǎng),我們對(duì)訂單系統(tǒng)開(kāi)始進(jìn)行第二次升級(jí)。目標(biāo)是保證系統(tǒng)有足夠的擴(kuò)展性,從而支撐業(yè)務(wù)的快速發(fā)展。
分布式系統(tǒng)的擴(kuò)展性依賴于分布式系統(tǒng)中各個(gè)組件的可擴(kuò)展性,針對(duì)訂單系統(tǒng)而言,其主要組成組件包括三類:存儲(chǔ)層、中間件層、服務(wù)層。下面將分層說(shuō)明如何提高各層的可擴(kuò)展性。
存儲(chǔ)層
訂單系統(tǒng)存儲(chǔ)層主要依賴于MySQL持久化、tair/redis cluster緩存。tair/redis cluster緩存本身即提供了很好的擴(kuò)展性。MySQL可以通過(guò)增加從庫(kù)來(lái)解決讀擴(kuò)展問(wèn)題。但是,對(duì)于寫MySQL存在單機(jī)容量的限制。另外,數(shù)據(jù)庫(kù)的整體容量受限于單機(jī)硬盤的限制。
存儲(chǔ)層的可擴(kuò)展性改造主要是對(duì)MySQL擴(kuò)展性改造。
分庫(kù)分表
寫容量限制是受限于MySQL數(shù)據(jù)庫(kù)單機(jī)處理能力限制。如果能將數(shù)據(jù)拆為多份,不同數(shù)據(jù)放在不同機(jī)器上,就可以方便對(duì)容量進(jìn)行擴(kuò)展。
對(duì)數(shù)據(jù)進(jìn)行拆分一般分為兩步,第一步是分庫(kù),即將不同表放不同庫(kù)不同機(jī)器上。經(jīng)過(guò)第一步分庫(kù)后,容量得到一定提升。但是,分庫(kù)并不能解決單表容量超過(guò)單機(jī)限制的問(wèn)題,隨著業(yè)務(wù)的發(fā)展,訂單系統(tǒng)中的訂單表即遇到了這個(gè)問(wèn)題。
針對(duì)訂單表超過(guò)單庫(kù)容量的問(wèn)題,需要進(jìn)行分表操作,即將訂單表數(shù)據(jù)進(jìn)行拆分。單表數(shù)據(jù)拆分后,解決了寫的問(wèn)題,但是如果查詢數(shù)據(jù)不在同一個(gè)分片,會(huì)帶來(lái)查詢效率的問(wèn)題(需要聚合多張表)。由于外賣在線業(yè)務(wù)對(duì)實(shí)時(shí)性、性能要求較高。我們針對(duì)每個(gè)主要的查詢維度均保存一份數(shù)據(jù)(每份數(shù)據(jù)按查詢維度進(jìn)行分片),方便查詢。
具體來(lái)說(shuō),外賣主要涉及三個(gè)查詢維度:訂單ID、用戶ID、門店ID。對(duì)訂單表分表時(shí),對(duì)于一個(gè)訂單,我們存三份,分別按照訂單ID、用戶ID、門店ID以一定規(guī)則存儲(chǔ)在每個(gè)維度不同分片中。這樣,可以分散寫壓力,同時(shí),按照訂單ID、用戶ID、門店ID三個(gè)維度查詢時(shí),數(shù)據(jù)均在一個(gè)分片,保證較高的查詢效率。
訂單表分表后,訂單表的存儲(chǔ)架構(gòu)如下所示:
可以看到,分表后,每個(gè)維度共有100張表,分別放在4個(gè)庫(kù)上面。對(duì)于同一個(gè)訂單,冗余存儲(chǔ)了三份。未來(lái),隨著業(yè)務(wù)發(fā)展,還可以繼續(xù)通過(guò)將表分到不同機(jī)器上來(lái)持續(xù)獲得容量的提升。
分庫(kù)分表后,訂單數(shù)據(jù)存儲(chǔ)到多個(gè)庫(kù)多個(gè)表中,為應(yīng)用層查詢帶來(lái)一定麻煩,解決分庫(kù)分表后的查詢主要有三種方案:
MySQL服務(wù)器端支持:目前不支持
中間件
應(yīng)用層
由于MySQL服務(wù)器端不能支持,我們只剩下中間件和應(yīng)用層兩個(gè)方案。中間件方案對(duì)應(yīng)用透明,但是開(kāi)發(fā)難度相對(duì)較大,當(dāng)時(shí)這塊沒(méi)有資源去支持。于是,我們采用應(yīng)用層方案來(lái)快速支持。結(jié)合應(yīng)用開(kāi)發(fā)框架(SPRING+MYBATIS),我們實(shí)現(xiàn)了一個(gè)輕量級(jí)的分庫(kù)分表訪問(wèn)插件,避免將分庫(kù)分表邏輯嵌入到業(yè)務(wù)代碼。分庫(kù)分表插件的實(shí)現(xiàn)包括如下幾個(gè)要點(diǎn)。
配置文件管理分庫(kù)分表配置信息;
JAVA注解說(shuō)明SQL語(yǔ)句分庫(kù)分表信息;
JAVA AOP解析注解+查詢配置文件,獲取數(shù)據(jù)源及表名;
MYBATIS動(dòng)態(tài)替換表名;
SPRING動(dòng)態(tài)替換數(shù)據(jù)源。
通過(guò)分庫(kù)分表,解決了寫容量擴(kuò)展問(wèn)題。但是分表后,會(huì)給查詢帶來(lái)一定的限制,只能支持主要維度的查詢,其它維度的查詢效率存在問(wèn)題。
ES搜索
訂單表分表之后,對(duì)于ID、用戶ID、門店ID外的查詢(比如按照手機(jī)號(hào)前綴查詢)存在效率問(wèn)題。這部分通常是復(fù)雜查詢,可以通過(guò)全文搜索來(lái)支持。在訂單系統(tǒng)中,我們通過(guò)ES來(lái)解決分表后非分表維度的復(fù)雜查詢效率問(wèn)題。具體來(lái)說(shuō),使用ES,主要涉及如下幾點(diǎn):
通過(guò)databus將訂單數(shù)據(jù)同步到ES。
同步數(shù)據(jù)時(shí),通過(guò)批量寫入來(lái)降低ES寫入壓力。
通過(guò)ES的分片機(jī)制來(lái)支持?jǐn)U展性。
小結(jié)
通過(guò)對(duì)存儲(chǔ)層的可擴(kuò)展性改造,使得訂單系統(tǒng)存儲(chǔ)層具有較好的可擴(kuò)展性。對(duì)于中間層的可擴(kuò)展性與上面提到的中間層可用性一樣,中間層本身已提供解決方案,直接復(fù)用即可。對(duì)于服務(wù)層,訂單系統(tǒng)服務(wù)層提供的都是無(wú)狀態(tài)服務(wù),對(duì)于無(wú)狀態(tài)服務(wù),通過(guò)增加機(jī)器,即可獲得更高的容量,完成擴(kuò)容。
通過(guò)對(duì)訂單系統(tǒng)各層可擴(kuò)展性改造,使得訂單系統(tǒng)具備了較好的可擴(kuò)展性,能夠支持業(yè)務(wù)的持續(xù)發(fā)展,當(dāng)前,訂單系統(tǒng)已具體千萬(wàn)單/日的容量。
上面幾部分都是在介紹如何通過(guò)架構(gòu)、技術(shù)實(shí)現(xiàn)等手段來(lái)搭建一個(gè)可靠、完善的訂單系統(tǒng)。但是,要保障系統(tǒng)的持續(xù)健康運(yùn)行,光搭建系統(tǒng)還不夠,運(yùn)維也是很重要的一環(huán)。
智能運(yùn)維的訂單系統(tǒng)
早期,對(duì)系統(tǒng)及業(yè)務(wù)的運(yùn)維主要是采用人肉的方式,即外部反饋問(wèn)題,RD通過(guò)排查日志等來(lái)定位問(wèn)題。隨著系統(tǒng)的復(fù)雜、業(yè)務(wù)的增長(zhǎng),問(wèn)題排查難度不斷加大,同時(shí)反饋問(wèn)題的數(shù)量也在逐步增多。通過(guò)人肉方式效率偏低,并不能很好的滿足業(yè)務(wù)的需求。
為提升運(yùn)維效率、降低人力成本,我們對(duì)系統(tǒng)及業(yè)務(wù)運(yùn)維進(jìn)行自動(dòng)化、智能化改進(jìn),改進(jìn)包括事前、事中、事后措施。
事前措施
事前措施的目的是為提前發(fā)現(xiàn)隱患,提前解決,避免問(wèn)題惡化。
在事前措施這塊,我們主要采取如下幾個(gè)手段:
定期線上壓測(cè):通過(guò)線上壓測(cè),準(zhǔn)確評(píng)估系統(tǒng)容量,提前發(fā)現(xiàn)系統(tǒng)隱患;
周期性系統(tǒng)健康體檢:通過(guò)周期檢測(cè)CPU利用率、內(nèi)存利用率、接口QPS、接口TP95、異常數(shù),取消訂單數(shù)等指標(biāo)是否異常,可以提前發(fā)現(xiàn)提前發(fā)現(xiàn)潛在問(wèn)題、提前解決;
全鏈路關(guān)鍵日志:通過(guò)記錄全鏈路關(guān)鍵日志,根據(jù)日志,自動(dòng)分析反饋訂單問(wèn)題原因,給出處理結(jié)果,有效提高反饋處理效率。
事中措施
事中措施的目的是為及時(shí)發(fā)現(xiàn)問(wèn)題、快速解決問(wèn)題。
事中這塊,我們采取的手段包括:
訂單監(jiān)控大盤:實(shí)時(shí)監(jiān)控訂單業(yè)務(wù)指標(biāo),異常時(shí)報(bào)警;
系統(tǒng)監(jiān)控大盤:實(shí)時(shí)監(jiān)控訂單系統(tǒng)指標(biāo),異常時(shí)報(bào)警;
完善的SOP:報(bào)警后,通過(guò)標(biāo)準(zhǔn)流程,快速定位問(wèn)題、解決問(wèn)題。
事后措施
事后措施是指問(wèn)題發(fā)生后,分析問(wèn)題原因,徹底解決。并將相關(guān)經(jīng)驗(yàn)教訓(xùn)反哺給事前、事中措施,不斷加強(qiáng)事先、事中措施,爭(zhēng)取盡量提前發(fā)現(xiàn)問(wèn)題,將問(wèn)題扼殺在萌芽階段。
通過(guò)將之前人肉進(jìn)行的運(yùn)維操作自動(dòng)化、智能化,提升了處理效率、減少了運(yùn)維的人力投入。
總結(jié)
以上是生活随笔為你收集整理的美团外卖订单中心的演进的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用Mac App Store更新、下载
- 下一篇: 怎么安装第二个路由器如何加装第二台路由器