大神分享美團(tuán)外賣訂單中心演進(jìn)之路
前言
美團(tuán)外賣從2013年9月成交首單以來(lái),已走過(guò)了三個(gè)年頭。時(shí)期,事務(wù)飛速開(kāi)展,美團(tuán)外賣由日均幾單開(kāi)展為日均500萬(wàn)單(9月11日已突破600萬(wàn))的大型O2O互聯(lián)網(wǎng)外賣服務(wù)渠道。渠道支撐的品類也由開(kāi)始外賣單品拓寬為全品類。
跟著訂單量的增加、事務(wù)復(fù)雜度的提高,外賣訂單體系也在不斷演化進(jìn)化,從前期一個(gè)訂單事務(wù)模塊到現(xiàn)在分布式可擴(kuò)展的高性能、高可用、高安穩(wěn)訂單體系。全部開(kāi)展過(guò)程中,訂單體系閱歷了幾個(gè)顯著的期間,下面本篇文章將為我們介紹一下訂單體系的演進(jìn)過(guò)程,重點(diǎn)重視各期間的事務(wù)特征、應(yīng)戰(zhàn)及應(yīng)對(duì)之道。
為便利我們非常好地了解全部演進(jìn)過(guò)程,我們首要看一下外賣事務(wù)。
外賣訂單業(yè)務(wù)
外賣訂單業(yè)務(wù)對(duì)于及時(shí)性的要求很高,因此從技術(shù)角度來(lái)看,實(shí)時(shí)性的優(yōu)先級(jí)很高,從用戶訂餐開(kāi)始算起,直至送達(dá),時(shí)效通常在一個(gè)小時(shí)左右。如果超時(shí),用戶體驗(yàn)就會(huì)受到傷害,成為一次糟糕的購(gòu)物經(jīng)歷。
在一個(gè)小時(shí)之內(nèi),訂單會(huì)不斷的變更狀態(tài),一直到最終送達(dá)。這期間要求各階段配合緊密,一定要保證訂單有效且及時(shí)送達(dá)。
下圖是一個(gè)用戶視角的訂單流程圖。

我們從一個(gè)普通用戶的思維出發(fā),當(dāng)他下達(dá)訂單之后,會(huì)有一個(gè)什么流程?
用戶需要下單然后支付,這是整個(gè)訂單發(fā)出的路徑,在這之后,商家接收訂單,完成制作,再之后,我們的物流團(tuán)隊(duì)進(jìn)行配送,送至終端用戶,然后就是確認(rèn)收貨、包括后續(xù)售后或完結(jié)訂單等操作。
從技術(shù)上團(tuán)隊(duì)來(lái)看,各個(gè)階段其實(shí)是多個(gè)子服務(wù)共同配的結(jié)果:比如說(shuō)用戶在訂單下達(dá)的階段可能會(huì)有需要各個(gè)購(gòu)物車、預(yù)覽、接受訂單服務(wù)共同匹配完成,這一系列的子服務(wù)又依賴于我們整體的底層基礎(chǔ)服務(wù)來(lái)完成。
另一個(gè)問(wèn)題在于,外賣業(yè)務(wù)的時(shí)效性非常顯著,訂單在中午、傍晚時(shí)段會(huì)大批量的集中爆發(fā),在其他時(shí)段數(shù)量則非常之少。這導(dǎo)致,到某時(shí)間段之后,整個(gè)系統(tǒng)的壓力會(huì)急劇上升。
下圖是一天內(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ù)起步階段技術(shù)團(tuán)隊(duì)的第一目標(biāo)是要能夠急速驗(yàn)證我們整體業(yè)務(wù)的可行性,所以這階段技術(shù)團(tuán)隊(duì)的主要任務(wù)就是保證我們的服務(wù)架構(gòu)有足夠的靈活性,方便快速迭代,完成業(yè)務(wù)快速試錯(cuò)過(guò)程中的需求。
因此,我們將訂單相關(guān)功能組織成為模塊化的服務(wù),將其與其他的模塊一起拼裝成jar包,這個(gè)包是公用的,可以通過(guò)我們的各個(gè)系統(tǒng)來(lái)使用這個(gè)包,從而提供訂單功能。
早期系統(tǒng)的整體架構(gòu)圖如下所示:

在業(yè)務(wù)前期使用這種架構(gòu),整體來(lái)講比較簡(jiǎn)單、靈活,整個(gè)公共服務(wù)的邏輯通過(guò)集成分配到各端,整個(gè)應(yīng)用的開(kāi)發(fā)部署相對(duì)比較簡(jiǎn)單,十分適合我們前期的需求:前面已經(jīng)提過(guò),是邏輯簡(jiǎn)單、業(yè)務(wù)量不大,方便與快速迭代。
但是,隨著業(yè)務(wù)量持續(xù)上升,整個(gè)服務(wù)體系邏輯變得復(fù)雜,業(yè)務(wù)量開(kāi)始增加,因此我們現(xiàn)有架構(gòu)的漏洞開(kāi)始出現(xiàn),整個(gè)業(yè)務(wù)體系互相干擾,出現(xiàn)了很多問(wèn)題。
我們考慮,在前期整個(gè)業(yè)務(wù)處在試探階段,初步的架構(gòu)可以滿足業(yè)務(wù)需求,也能夠給提供快速迭代的支持,但隨著整個(gè)業(yè)務(wù)的成長(zhǎng)、服務(wù)的成熟,我們應(yīng)該對(duì)這個(gè)體系進(jìn)行升級(jí),滿足現(xiàn)階段的需求。
獨(dú)立的訂單系統(tǒng)
在14年的4月左右,外賣訂單數(shù)量增長(zhǎng)迅速,幾乎達(dá)到每天10萬(wàn)訂單量的水平,而且由于業(yè)務(wù)發(fā)展良好,這個(gè)數(shù)字每天都在不斷攀升。整體業(yè)務(wù)的大框架此時(shí)已經(jīng)基本成型,集體業(yè)務(wù)在整體框架上快速迭代。
業(yè)務(wù)團(tuán)隊(duì)使用一個(gè)大項(xiàng)目進(jìn)行開(kāi)發(fā)部署,在此基礎(chǔ)上互相影響,業(yè)務(wù)溝通成本上升,大多數(shù)業(yè)務(wù)公用VM的情況,也對(duì)業(yè)務(wù)整體產(chǎn)生了一定影響。
為解決開(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ò)接口提供給外部使用。
在內(nèi)部訂單系統(tǒng)中,我們?cè)u(píng)估了功能優(yōu)先級(jí),按照優(yōu)先級(jí)拆分成了不同的子系統(tǒng),以防止業(yè)務(wù)之間的相互影響,通過(guò)隊(duì)列消息的形式,訂單系統(tǒng)可以通知外部訂單狀態(tài)的變更等情況。
獨(dú)立拆分后的訂單系統(tǒng)架構(gòu)如下所示:

這其中,最底層是數(shù)據(jù)存儲(chǔ)層,負(fù)責(zé)訂單相關(guān)數(shù)據(jù)的獨(dú)立存儲(chǔ)。訂單服務(wù)層,該層按照優(yōu)先級(jí)劃分為三個(gè)體系,分別稱之為交易體系、查詢體系和異步處理的體系。
獨(dú)立拆分后,能夠避免事務(wù)間的相互影響。迅速支持事務(wù)迭代需要的一起,保障體系穩(wěn)定性。
高性能、高可用、高穩(wěn)定的訂單系統(tǒng)
在我們將訂單系統(tǒng)進(jìn)行拆分后,業(yè)務(wù)之間的相互干擾大大降低,不僅保證了迭代的速度,而且還很好的維持了系統(tǒng)的穩(wěn)定性,在這期間,整個(gè)業(yè)務(wù)的訂單量開(kāi)始逐漸想著百萬(wàn)大關(guān)邁進(jìn),并逐漸超出。本來(lái)的小問(wèn)題,在大量訂單出現(xiàn)的時(shí)候覆蓋面積加大,對(duì)用戶的試用體驗(yàn)相當(dāng)不友好。舉例說(shuō)明,再支付成功后,某些極端情況會(huì)導(dǎo)致支付成功的消息無(wú)法返回,在終端顯示沒(méi)有支付。在巨量訂單的前提下,這種問(wèn)題開(kāi)始增加,我們必須進(jìn)一步優(yōu)化系統(tǒng)的可靠性,保證我們的訂單功能不會(huì)影響用戶使用。
不僅如此,訂單量仍在不斷增加的同時(shí),一些業(yè)務(wù)邏輯相對(duì)復(fù)雜、混亂,對(duì)于整個(gè)系統(tǒng)的使用提出了新的、更高的要求。
因此,為了能夠建設(shè)一個(gè)更加穩(wěn)定并且可信賴的訂單服務(wù)系統(tǒng),我們必須再次對(duì)整個(gè)系統(tǒng)進(jìn)行升級(jí)。我們后文就會(huì)按照各個(gè)升級(jí)需求對(duì)整個(gè)升級(jí)過(guò)程進(jìn)行描述。
性能優(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è)方面。
異步化
一個(gè)顯而易見(jiàn)的道理是,同一時(shí)間需要處理的事情越少,服務(wù)性能就會(huì)越高、速度越快,所以我們將通過(guò)將部分操作進(jìn)行異步化處理減少整個(gè)操作進(jìn)行的壓力。通過(guò)異步來(lái)提升服務(wù)氣的性能。
以下使我們提出的兩種方案:
- 線程或線程池:將異步操作放在單獨(dú)線程中處理,避免阻塞服務(wù)線程;
- 消息異步:異步操作通過(guò)接收消息完成。
注意合理有一個(gè)隱患,我們?nèi)绾伪U袭惒讲僮鞯膱?zhí)行?設(shè)想一下場(chǎng)景,當(dāng)應(yīng)用重啟時(shí),如果是線程或者線程池的行的異步化,在后臺(tái)執(zhí)行未完成的情況下,jvm重啟會(huì)造成相當(dāng)大的影響。
因此需要采取優(yōu)雅關(guān)閉開(kāi)保障業(yè)務(wù)的進(jìn)行。當(dāng)然,如果采取消息異步,則無(wú)須考慮這個(gè)問(wèn)題。
具體到該系統(tǒng),我們選擇將某些沒(méi)有必要同步進(jìn)行的操作異步化,從而提供更強(qiáng)的性能,例如我們發(fā)放紅包或者推送消息等等全部采用了異步處理。
以訂單配送PUSH推送為例,將PUSH推送異步化后的處理流程變更如下所示:

PUSH異步化后,線程#1在更新訂單狀態(tài)、發(fā)送消息后立即返回,而不用同步等待PUSH推送完成。而PUSH推送異步在線程#2中完成。
并行化
操作并行化也是提升性能的一大利器,并行化將原本串行的工作并行執(zhí)行,降低整體處理時(shí)間。我們對(duì)所有訂單服務(wù)進(jìn)行分析,將其中非相互依賴的操作并行化,從而提升整體的響應(yīng)時(shí)間。
以用戶下單為例,第一步是從各個(gè)依賴服務(wù)獲取信息,包括門店、菜品、用戶信息等。獲取這些信息并不需要相互依賴,故可以將其并行化,并行后的處理流程變更如下所示:

通過(guò)將獲取信息并行化,可有效縮短下單時(shí)間,提升下單接口性能。
緩存
經(jīng)過(guò)將核算信息進(jìn)行提早核算后緩存,防止獲取數(shù)據(jù)時(shí)進(jìn)行實(shí)時(shí)核算,然后提升獲取核算數(shù)據(jù)的效勞功能。比如關(guān)于首單、用戶已減免配送費(fèi)等,經(jīng)過(guò)提早核算后緩存,能夠簡(jiǎn)化實(shí)時(shí)獲取數(shù)據(jù)邏輯,節(jié)省時(shí)刻。
以用戶已減免配送費(fèi)為例,假如需求實(shí)時(shí)核算,則需求取到用戶一切訂單后,再進(jìn)行核算,這么實(shí)時(shí)核算成本較高。技術(shù)團(tuán)隊(duì)經(jīng)過(guò)提早核算,緩存用戶已減免配送費(fèi)。需求取用戶已減免配送費(fèi)時(shí),從緩存中取即可,不用實(shí)時(shí)核算。具體來(lái)說(shuō),包含如下幾點(diǎn):
- 通過(guò)緩存保存用戶已減免配送費(fèi);
- 用戶下單時(shí),如果訂單有減免配送費(fèi),增加緩存中用戶減免配送費(fèi)金額(異步進(jìn)行);
- 訂單取消時(shí),如果訂單有減免配送費(fèi),減少緩存中用戶減免配送費(fèi)金額(異步進(jìn)行);
一致性優(yōu)化
訂單體系觸及買賣,需要確保數(shù)據(jù)的共同性。不然,一旦出現(xiàn)疑問(wèn),可能會(huì)致使訂單不能及時(shí)配送、買賣金額不對(duì)等。
買賣一個(gè)很主要的特征是其操作具有業(yè)務(wù)性,訂單體系是一個(gè)雜亂的分布式體系,比方付出觸及訂單體系、付出渠道、付出寶/網(wǎng)銀等第三方。僅經(jīng)過(guò)傳統(tǒng)的數(shù)據(jù)庫(kù)業(yè)務(wù)來(lái)確保不太可行。關(guān)于訂單買賣體系的業(yè)務(wù)性,并不請(qǐng)求嚴(yán)厲滿意傳統(tǒng)數(shù)據(jù)庫(kù)業(yè)務(wù)的ACID性質(zhì),只需要終究成果共同即可。對(duì)于訂單體系的特征,咱們經(jīng)過(guò)如下種方法來(lái)確保終究成果的共同性。
重試/冪等
經(jīng)過(guò)延時(shí)重試,確保操作終究會(huì)最執(zhí)行。比方退款操作,如退款時(shí)遇到網(wǎng)絡(luò)或付出渠道毛病等疑問(wèn),會(huì)延時(shí)進(jìn)行重試,確保退款終究會(huì)被完結(jié)。重試又會(huì)帶來(lái)另一個(gè)疑問(wèn),即有些操作重復(fù)進(jìn)行,需要對(duì)操作進(jìn)行冪等處理,確保重試的正確性。
以退款操作為例,參加重試/冪等后的處理流程如下所示:

退款操作首先會(huì)查看是否現(xiàn)已退款,假如現(xiàn)已退款,直接返回。不然,向付出渠道建議退款,從而確保操作冪等,防止重復(fù)操作帶來(lái)疑問(wèn)。假如建議退款失利(比方網(wǎng)絡(luò)或付出渠道毛病),會(huì)將使命放入延時(shí)行列,稍后重試。不然,直接返回。
經(jīng)過(guò)重試+冪等,能夠確保退款操作終究一定會(huì)完結(jié)。
2PC
2PC是指分布式業(yè)務(wù)的兩期間提交,經(jīng)過(guò)2PC來(lái)確保多個(gè)體系的數(shù)據(jù)一致性。比方下單過(guò)程中,觸及庫(kù)存、優(yōu)惠資歷等多個(gè)資本,下單時(shí)會(huì)首先預(yù)占資本(對(duì)應(yīng)2PC的第一期間),下單失利后會(huì)釋放資本(對(duì)應(yīng)2PC的回滾期間),成功后會(huì)運(yùn)用資本(對(duì)應(yīng)2PC的提交期間)。關(guān)于2PC,網(wǎng)上有很多的說(shuō)明,這兒不再持續(xù)打開(kāi)。
高可用
分布式體系的可用性由其各個(gè)組件的可用性一起決議,要提高分布式體系的可用性,需求歸納提高構(gòu)成分布式體系的各個(gè)組件的可用性。
對(duì)于訂單體系而言,其主要構(gòu)成組件包括三類:存儲(chǔ)層、中間件層、效勞層。下面將分層說(shuō)明訂單體系的可用性。
存儲(chǔ)層
存儲(chǔ)層的組件如MySQL、ES等自身現(xiàn)已完成了高可用,比方MySQL經(jīng)過(guò)主從集群、ES經(jīng)過(guò)分片仿制來(lái)完成高可用。存儲(chǔ)層的高可用依靠各個(gè)存儲(chǔ)組件即可。
中間件層
分布式體系會(huì)大量用到各類中間件,比方服務(wù)調(diào)用結(jié)構(gòu)等,這類中間件通常使用開(kāi)源商品或由公司根底渠道供給,自身已具有高可用。
服務(wù)層
在分布式體系中,各個(gè)服務(wù)間經(jīng)過(guò)彼此調(diào)用來(lái)完成事務(wù)功用,一旦某個(gè)服務(wù)出現(xiàn)問(wèn)題,會(huì)級(jí)聯(lián)影響調(diào)用方的其他服務(wù),進(jìn)而致使體系潰散。分布式體系中的依靠容災(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é)
上面都是經(jīng)過(guò)架構(gòu)、技能完成層面來(lái)保證訂單體系的功能、安穩(wěn)性、可用性。實(shí)際中,有很多的事端是人為因素致使的,除了好的架構(gòu)、技能完成外,經(jīng)過(guò)標(biāo)準(zhǔn)、準(zhǔn)則來(lái)躲避人為事端也是保證功能、安穩(wěn)性、可用性的重要方面。訂單體系經(jīng)過(guò)完善需要review、計(jì)劃評(píng)定、代碼review、測(cè)驗(yàn)上線、后續(xù)跟進(jìn)流程來(lái)防止人為因素影響訂單體系安穩(wěn)性。
經(jīng)過(guò)以上辦法,技術(shù)團(tuán)隊(duì)將訂單體系建造成了一個(gè)高功能、高安穩(wěn)、高可用的分布式體系。其中,交易體系tp99為150ms、查詢體系tp99時(shí)刻為40ms。全體體系可用性為6個(gè)9。
可擴(kuò)展的訂單系統(tǒng)
訂單體系通過(guò)上面介紹的全體晉級(jí)后,已經(jīng)是一個(gè)高功能、高安穩(wěn)、高可用的分布式體系。可是體系的的可拓展性還存在必定疑問(wèn),部分效勞只能通過(guò)筆直拓展(添加效勞器裝備)而不能通過(guò)水平拓展(加機(jī)器)來(lái)進(jìn)行擴(kuò)容。可是,效勞器裝備有上限,致使效勞全體容量受到約束。
到2015年5月的時(shí)分,這個(gè)疑問(wèn)就比較突出了。其時(shí),數(shù)據(jù)庫(kù)效勞器寫挨近單機(jī)上限。事務(wù)預(yù)期還會(huì)持續(xù)快速增長(zhǎng)。為確保事務(wù)的快速增長(zhǎng),咱們對(duì)訂單體系開(kāi)始進(jìn)行第2次晉級(jí)。方針是確保體系有滿足的拓展性,然后支持事務(wù)的快速開(kāi)展。
分布式體系的拓展性依賴于分布式體系中各個(gè)組件的可拓展性,關(guān)于訂單體系而言,其首要組成組件包含三類:存儲(chǔ)層、中間件層、效勞層。下面將分層闡明怎么進(jìn)步各層的可拓展性。
存儲(chǔ)層
訂單體系存儲(chǔ)層首要依賴于MySQL耐久化、tair/redis cluster緩存。tair/redis cluster緩存自身即提供了極好的拓展性。MySQL能夠通過(guò)添加從庫(kù)來(lái)處理讀拓展疑問(wèn)??墒?,關(guān)于寫MySQL存在單機(jī)容量的約束。另外,數(shù)據(jù)庫(kù)的全體容量受限于單機(jī)硬盤的約束。
存儲(chǔ)層的可拓展性改造首要是對(duì)MySQL拓展性改造。
- 分庫(kù)分表
寫容量約束是受限于MySQL數(shù)據(jù)庫(kù)單機(jī)處理才能約束。假如能將數(shù)據(jù)拆為多份,不一樣數(shù)據(jù)放在不一樣機(jī)器上,就能夠便利對(duì)容量進(jìn)行拓展。
對(duì)數(shù)據(jù)進(jìn)行拆分通常分為兩步,第一步是分庫(kù),行將不一樣表放不一樣庫(kù)不一樣機(jī)器上。通過(guò)第一步分庫(kù)后,容量得到必定提高。可是,分庫(kù)并不能處理單表容量超越單機(jī)約束的疑問(wèn),跟著事務(wù)的開(kāi)展,訂單體系中的訂單表即遇到了這個(gè)疑問(wèn)。
關(guān)于訂單表超越單庫(kù)容量的疑問(wèn),需求進(jìn)行分表操作,行將訂單表數(shù)據(jù)進(jìn)行拆分。單表數(shù)據(jù)拆分后,處理了寫的疑問(wèn),可是假如查詢數(shù)據(jù)不在同一個(gè)分片,會(huì)帶來(lái)查詢功率的疑問(wèn)(需求聚合多張表)。因?yàn)橥赓u在線事務(wù)對(duì)實(shí)時(shí)性、功能請(qǐng)求較高。咱們關(guān)于每個(gè)首要的查詢維度均保留一份數(shù)據(jù)(每份數(shù)據(jù)按查詢維度進(jìn)行分片),便利查詢。
具體來(lái)說(shuō),外賣首要涉及三個(gè)查詢維度:訂單ID、用戶ID、門店ID。對(duì)訂單表分表時(shí),關(guān)于一個(gè)訂單,咱們存三份,別離依照訂單ID、用戶ID、 門店ID以必定規(guī)矩存儲(chǔ)在每個(gè)維度不一樣分片中。這么,能夠渙散寫壓力,一起,依照訂單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)維的人力投入。