“高并發(fā)”一直是大家感興趣的話題。本文就來(lái)給大家講講機(jī)票高并發(fā)的故事。
背景介紹
Qunar是2005年成立的,那時(shí)候人們還不習(xí)慣通過(guò)打電話或者到代理商那里去買機(jī)票。近幾年隨著旅游業(yè)的發(fā)展,機(jī)票業(yè)務(wù)也由傳統(tǒng)的線下來(lái)到線上。在“在線旅游”的大浪潮下,Qunar的核心業(yè)務(wù)主要是線上機(jī)票搜索和機(jī)票銷售。根據(jù)2014年9月艾瑞監(jiān)測(cè)數(shù)據(jù),在旅行類網(wǎng)站月度獨(dú)立訪問(wèn)量統(tǒng)計(jì)中,去哪兒網(wǎng)以4474萬(wàn)人名列前茅。截至2015年3月31日,去哪兒網(wǎng)可實(shí)時(shí)搜索約9000家旅游代理商網(wǎng)站,搜索范圍覆蓋全球范圍內(nèi)超過(guò)28萬(wàn)條國(guó)內(nèi)及國(guó)際航線。
Qunar由機(jī)票起家,核心產(chǎn)品包括機(jī)票搜索比價(jià)系統(tǒng)、機(jī)票銷售OTA系統(tǒng)等。后來(lái)一度成為國(guó)內(nèi)最大旅游搜索引擎,所以最開(kāi)始大家知道Qunar都是從機(jī)票開(kāi)始。
為了方便大家了解機(jī)票搜索的具體業(yè)務(wù),我們從用戶熟悉角度看一下搜索的過(guò)程,如下圖:
根據(jù)上面的圖片,簡(jiǎn)單解釋下:
金喜正規(guī)買球:用戶按出發(fā)城市、到達(dá)城市、出發(fā)日期開(kāi)始搜索機(jī)票,進(jìn)入列表頁(yè)。
列表頁(yè):展示第一次搜索結(jié)果,一般用戶會(huì)多次搜索,直到找到適合他的航班,然后進(jìn)入詳情頁(yè)。
產(chǎn)品詳情頁(yè):用戶填入個(gè)人信息,開(kāi)始準(zhǔn)備下單支付。
從上面的介紹可以看出,過(guò)程1和2是個(gè)用戶高頻的入口。用戶訪問(wèn)流量一大,必然有高并發(fā)的情況。所以在金喜正規(guī)買球和列表頁(yè)會(huì)做一些優(yōu)化:
前端做靜態(tài)文件的壓縮,優(yōu)化Http請(qǐng)求連接數(shù),以減小帶寬,讓頁(yè)面更快加載出來(lái)。
前后端做了數(shù)據(jù)分離,讓搜索服務(wù)解耦,在高并發(fā)情況下更靈活做負(fù)載均衡。
后端數(shù)據(jù)(航班數(shù)據(jù))99%以上來(lái)自緩存,加載快,給用戶更快的體驗(yàn)。而我們的緩存是 異步刷新的機(jī)制,后面會(huì)提及到。
在過(guò)億級(jí)UV的搜索業(yè)務(wù),其搜索結(jié)果核心指標(biāo):一是保證時(shí)間夠快,二是保證結(jié)果實(shí)時(shí)最新。
為了達(dá)到這個(gè)指標(biāo),搜索結(jié)果就要盡量走緩存,我們會(huì)預(yù)先把航班數(shù)據(jù)放到緩存,當(dāng)航班數(shù)據(jù)變化時(shí),增量更新緩存系統(tǒng)。 所以,Qunar機(jī)票技術(shù)部就有一個(gè)全年很關(guān)鍵的一個(gè)指標(biāo):搜索緩存命中率,當(dāng)時(shí)已經(jīng)做到了>99.7%。再往后,每提高0.1%,優(yōu)化難度成指數(shù)級(jí)增長(zhǎng)了。哪怕是千分之一,也直接影響用戶體驗(yàn),影響每天上萬(wàn)張機(jī)票的銷售額。
這里還有幾個(gè)值得關(guān)注的指標(biāo):
每臺(tái)搜索實(shí)例的QPS(搜索有50~60臺(tái)虛擬機(jī)實(shí)例,按最大并發(fā)量,每臺(tái)請(qǐng)求吞吐量>1000)。
搜索結(jié)果的 Average-Time : 一般從C端用戶體驗(yàn)來(lái)說(shuō),Average-Time 不能超過(guò)3秒的。
了解完機(jī)票搜索大概的流程,下面就來(lái)看看Qunar搜索的架構(gòu)。
搜索系統(tǒng)設(shè)計(jì)架構(gòu)
Qunar搜索架構(gòu)圖
上面提到搜索的航班數(shù)據(jù)都是存儲(chǔ)在緩存系統(tǒng)里面。最早使用Memcached,通過(guò)一致Hash建立集群,印象大概有20臺(tái)左右實(shí)例。 存儲(chǔ)的粒度就是出發(fā)地和到達(dá)地全部航班數(shù)據(jù)。隨著當(dāng)時(shí)Redis并發(fā)讀寫性能穩(wěn)步提高,部分系統(tǒng)開(kāi)始逐步遷移到Redis,比如機(jī)票低價(jià)系統(tǒng)、推薦系統(tǒng)。
搜索系統(tǒng)按架構(gòu)圖,主要定義成前臺(tái)搜索、后臺(tái)搜索兩大模塊,分別用2、3標(biāo)示,下面我也會(huì)重點(diǎn)解釋。
前臺(tái)搜索
主要讀取緩存,解析,合并航班數(shù)據(jù)返回給用戶端。
前臺(tái)搜索是基于Web服務(wù),高峰期時(shí)候最大啟動(dòng)了50臺(tái)左右的Tomcat實(shí)例。搜索的URL規(guī)則是:出發(fā)城市+到達(dá)城市+出發(fā)日期,這和緩存系統(tǒng)存儲(chǔ)最小單元:出發(fā)城市+到達(dá)城市+出發(fā)日期是一致的。
Tomcat服務(wù)我們是通過(guò)Nginx來(lái)做負(fù)載均衡,用Lua腳本區(qū)分是國(guó)際航線還是國(guó)內(nèi)航線,基于航線類型,Nginx會(huì)跳轉(zhuǎn)不同搜索服務(wù)器:主要是國(guó)際搜索、國(guó)內(nèi)搜索(基于業(yè)務(wù)、數(shù)據(jù)模型、商業(yè)模式,完全分開(kāi)部署)。不光如此,Lua還用來(lái)敏捷開(kāi)發(fā)一些基本服務(wù):比如維護(hù)城市列表、機(jī)場(chǎng)列表等。
航班數(shù)據(jù)
上文我一直提到航班數(shù)據(jù),接下來(lái)簡(jiǎn)單介紹下航班的概念和基本類型,讓大家有個(gè)印象,明白的同學(xué)可以跳過(guò):
單程航班:也叫直達(dá)航班,比如BJ(北京)飛NY(紐約)。
往返航班:比如BJ飛NY,然后又從NY返回BJ。
帶中轉(zhuǎn):有單程中轉(zhuǎn)、往返中轉(zhuǎn);往返中轉(zhuǎn)可以一段直達(dá),一段中轉(zhuǎn)。也可以兩段都有中轉(zhuǎn),如下圖:
其實(shí),還有更復(fù)雜的情況:
如果哪天在BJ(北京)的你想來(lái)一次說(shuō)走就走的旅行,想要去NY(紐約)。你選擇了BJ直飛NY的單程航班。后來(lái),你覺(jué)得去趟米國(guó)老不容易,想順便去LA玩。那你可以先BJ飛到LA,玩幾天,然后LA再飛NY。
不過(guò),去了米國(guó)要回來(lái)吧,你也許:
NY直接飛回BJ。
突然玩性大發(fā),中途順便去日本,從NY飛東京,再?gòu)臇|京飛BJ。
還沒(méi)玩夠?還要從NY飛夏威夷玩,然后夏威夷飛東京,再東京飛首爾,最后首爾返回北京。
…… 有點(diǎn)復(fù)雜吧,這是去程中轉(zhuǎn)、回程多次中轉(zhuǎn)的航班路線。
對(duì)應(yīng)國(guó)際航班還算非常正常的場(chǎng)景,比如從中國(guó)去肯尼亞、阿根廷,因?yàn)闆](méi)有直達(dá)航班,就會(huì)遇到多次中轉(zhuǎn)。所以,飛國(guó)外有時(shí)候是蠻有意思、蠻麻煩的一件事。
通過(guò)上面例子,大家了解到了機(jī)票中航線的復(fù)雜程度。但是,我們的緩存其實(shí)是有限的,它只保存了兩個(gè)地方的航班信息。這樣簡(jiǎn)單的設(shè)計(jì)也是有必然出發(fā)點(diǎn):考慮用最簡(jiǎn)單的兩點(diǎn)一線,才能最大限度上組合復(fù)雜的線路。
所以在前臺(tái)搜索,還有大量工作要做,總而言之就是:
按照最終出發(fā)地、目的地,根據(jù)一定規(guī)則搜索出用戶想要的航班路線。這些規(guī)則可能是:飛行時(shí)間最短、機(jī)票價(jià)格最便宜(一般中轉(zhuǎn)就會(huì)便宜)、航班中轉(zhuǎn)最少、最宜飛行時(shí)間。
你看,機(jī)票里面的航線是不是變成了數(shù)據(jù)結(jié)構(gòu)里面的有向圖,而搜索就等于在這個(gè)有向圖中,按照一定的權(quán)重求出最優(yōu)路線的過(guò)程!
高并發(fā)下多線程應(yīng)用
我們后端技術(shù)棧基于Java。為了搜索變得更快,我們大量把Java多線程特性用到了并行運(yùn)算上。這樣,充分利用CPU資源,讓計(jì)算航線變得更快。 比如下面這樣中轉(zhuǎn)航線,就會(huì)以多線程方式并行先處理每一段航班。類似這樣場(chǎng)景很多:
Java的多線程對(duì)于高并發(fā)系統(tǒng)有下面的優(yōu)勢(shì):
Java Executor框架提供了完善線程池管理機(jī)制:譬如newCachedThreadPool、 SingleThreadExecutor 等線程池。
FutureTask類靈活實(shí)現(xiàn)多線程的并行、串行計(jì)算。
在高并發(fā)場(chǎng)景下,提供了保證線程安全的對(duì)象、方法。比如經(jīng)典的ConcurrentHashMap,它比起HashMap,有更小粒度的鎖,并發(fā)讀寫性能更好。線程安全的StringBuilder取代String、StringBuffer等等(Java在多線程這塊實(shí)現(xiàn)是非常優(yōu)秀和成熟的)。
高并發(fā)下數(shù)據(jù)傳輸
因?yàn)槊看嗡阉鳈C(jī)票,返回的航班數(shù)據(jù)是很多的:
包含各種航線組合:?jiǎn)纬獭纬桃淮沃修D(zhuǎn)、單程多次中轉(zhuǎn),往返更不用說(shuō)了。
航線上又區(qū)分上百種航空公司的組合。比如北京到紐約,有美國(guó)航空,國(guó)航,大韓, 東京等等各個(gè)國(guó)家的各大航空公司,琳瑯滿目。
那么,最早航班數(shù)據(jù)用標(biāo)準(zhǔn)的XML、JSON存儲(chǔ),不過(guò)隨著搜索量不斷飆升,CPU和帶寬壓力很大了。后來(lái)采取自己定義一種txt格式來(lái)傳輸數(shù)據(jù):一方面數(shù)據(jù)壓縮到原來(lái)30%~40%,極大的節(jié)約了帶寬。同時(shí)CPU的運(yùn)算量大大減低,服務(wù)器數(shù)量也隨之減小。
在大用戶量、高并發(fā)的情況下,是特別能看出開(kāi)源系統(tǒng)的特點(diǎn):比如機(jī)票的數(shù)據(jù)解析用到了很多第三方庫(kù),當(dāng)時(shí)我們也用了Fastjson。在正常情況下,F(xiàn)astjson 確實(shí)解析很快,一旦并發(fā)量上來(lái),就會(huì)越來(lái)越吃內(nèi)存,甚至JVM很快出現(xiàn)內(nèi)存溢出。原因呢,很簡(jiǎn)單,F(xiàn)astjson設(shè)計(jì)初衷是:先把整個(gè)數(shù)據(jù)裝載到內(nèi)存,然后解析,所以執(zhí)行很快,但很費(fèi)內(nèi)存。
當(dāng)然,這不能說(shuō)Fastjson不優(yōu)秀,現(xiàn)在看 GitHub上有8000多star。只是它不適應(yīng)剛才的業(yè)務(wù)場(chǎng)景。
這里順便說(shuō)到聯(lián)想到一個(gè)事:互聯(lián)網(wǎng)公司因?yàn)榭焖侔l(fā)展,需要新技術(shù)來(lái)支撐業(yè)務(wù)。 那么,應(yīng)用新的技術(shù)應(yīng)該注意些什么呢?我的體會(huì)是:
好的技術(shù)要大膽嘗試,謹(jǐn)慎使用。
優(yōu)秀開(kāi)源項(xiàng)目,注意是優(yōu)秀。使用前一定弄清他的使用場(chǎng)景,多做做壓力測(cè)試。
高并發(fā)的用戶系統(tǒng)要做A/B測(cè)試,然后逐步導(dǎo)流,最后上線后還要有個(gè)觀察期。
后臺(tái)搜索
后臺(tái)搜索系統(tǒng)的核心任務(wù)是從外部的GDS系統(tǒng)抓取航班數(shù)據(jù),然后異步寫入緩存。
首先說(shuō)一個(gè)概念GDS(Global Distribution System)即“全球分銷系統(tǒng)”,是應(yīng)用于民用航空運(yùn)輸及整個(gè)旅游業(yè)的大型計(jì)算機(jī)信息服務(wù)系統(tǒng)。通過(guò)GDS,遍及全球的旅游銷售機(jī)構(gòu)可以及時(shí)地從航空公司、旅館、租車公司、旅游公司獲取大量的與旅游相關(guān)的信息。
機(jī)票的源數(shù)據(jù)都來(lái)自于各種GDS系統(tǒng),但每個(gè)GDS卻千差萬(wàn)別:
服務(wù)器遍布全球各地:國(guó)內(nèi)GDS主要有中航信的IBE系統(tǒng)、黑屏數(shù)據(jù)(去機(jī)場(chǎng)、火車站看到售票員輸入的電腦終端系統(tǒng)),國(guó)際GDS遍布于東南亞、北美、歐洲等等。
通訊協(xié)議不一樣,HTTP(API、Webservice)、Socket等等。
服務(wù)不穩(wěn)定,尤其國(guó)外的GDS,受網(wǎng)路鏈路影響,訪問(wèn)很慢(十幾分鐘長(zhǎng)連接很常見(jiàn)),服務(wù)白天經(jīng)常性掛掉。
更麻煩的是:GDS一般付費(fèi)按次查詢,在大搜索量下,實(shí)時(shí)付費(fèi)用它,估計(jì)哪家公司都得破產(chǎn)。而且就算有錢 , 各種歷史悠久的GDS是無(wú)法承載任何的高并發(fā)查詢。更苦的是,因?yàn)槭莿?chuàng)業(yè)公司,我們大都只能用免費(fèi)的GDS,它們都是極其不穩(wěn)定的。
所謂便宜沒(méi)好貨,最搞笑的一次是:曾經(jīng)在米國(guó)的GDS掛了一、兩天,技術(shù)們想聯(lián)系服務(wù)商溝通服務(wù)器問(wèn)題。因?yàn)槭敲赓M(fèi),就沒(méi)有所謂的服務(wù)商一說(shuō),最后產(chǎn)品總監(jiān)(算兼職商務(wù)吧)給了一個(gè)國(guó)外的網(wǎng)址,打開(kāi)是這家服務(wù)商的工單頁(yè)面,全英文,沒(méi)有留任何郵箱。提交工單后,不知道什么時(shí)候回復(fù)。可以想想當(dāng)時(shí)我的心情......
雖然有那么多困難,我們還是找到一些技術(shù)方案,具體如下。
引入NIO框架
考慮GDS訪問(wèn)慢,不穩(wěn)定,導(dǎo)致很多長(zhǎng)連接。我們大量使用NIO技術(shù):
NIO,是為了彌補(bǔ)傳統(tǒng)I/O工作模式的不足而研發(fā)的,NIO的工具包提出了基于Selector(選擇器)、Buffer(緩沖區(qū))、Channel(通道)的新模式;Selector(選擇器)、可選擇的Channel(通道)和SelectionKey(選擇鍵)配合起來(lái)使用,可以實(shí)現(xiàn)并發(fā)的非阻塞型I/O能力。
NIO并不是一下就憑空出來(lái)的,那是因?yàn)?Epoll 在Linux2.6內(nèi)核中正式引入,有了I/O多路復(fù)用技術(shù),它可以處理更多的并發(fā)連接。這才出現(xiàn)了各種應(yīng)用層的NIO框架。
HTTP、Socket 都支持了NIO方式,在和GDS通信過(guò)程中,和過(guò)去相比:
通信從同步變成異步模式:CPU的開(kāi)銷、內(nèi)存的占用都減低了一個(gè)數(shù)量級(jí)。
長(zhǎng)連接可以支持更長(zhǎng)超時(shí)時(shí)間,對(duì)國(guó)外GDS通信要可靠多了。
提高了后臺(tái)搜索服務(wù)器的穩(wěn)定性。
消息隊(duì)列
為了異步完成航班數(shù)據(jù)更新到緩存,我們采用消息隊(duì)列方式(主備AMQ)來(lái)管理這些異步任務(wù)。具體實(shí)現(xiàn)如下。
有一個(gè)問(wèn)題,如何判斷緩存過(guò)期呢?這里面有一個(gè)復(fù)雜的系統(tǒng)來(lái)設(shè)置的,它叫Router。資深運(yùn)營(yíng)會(huì)用它設(shè)置可以細(xì)化到具體一個(gè)航段的緩存有效期:比如說(shuō)北京—NY,一般來(lái)說(shuō)買機(jī)票的人不多的,航班信息緩存幾天都沒(méi)有問(wèn)題。但如果北京—上海,那可能就最多5分鐘了。
Router還有一個(gè)復(fù)雜工作,我叫它“去偽存真”。我們長(zhǎng)期發(fā)現(xiàn)(真是便宜無(wú)好貨),某些GDS返回航班數(shù)據(jù)不全是準(zhǔn)確的,所以我們會(huì)把某些航線、甚至航班指定具體的GDS數(shù)據(jù)源,比如北京—新加坡:直達(dá)航班數(shù)據(jù) 來(lái)自于ABAQUS,但是中轉(zhuǎn)數(shù)據(jù),北京—上海—新加坡, 或者北京—臺(tái)北—新加坡 從IBE來(lái)會(huì)精準(zhǔn)些。
因此Router路由規(guī)則設(shè)計(jì)要很靈活。通過(guò)消息隊(duì)列,也其實(shí)采用異步化方式讓服務(wù)解耦,進(jìn)行了很好的讀寫分離。
GDS服務(wù)抽象虛擬Node
為了管理好不同GDS資源,最大的利用它們。我們把GDS服務(wù)器抽象成一組Node節(jié)點(diǎn)來(lái)便于管理,像下面這樣:
具體原理:按照每個(gè)GDS服務(wù)器穩(wěn)定性(通過(guò)輪休方式,不斷Check它們的可用性)和查詢性能,我們算出一個(gè)合理的權(quán)重,給它分配對(duì)應(yīng)的一組虛擬的Node節(jié)點(diǎn),這些Node節(jié)點(diǎn)由一個(gè)Node池統(tǒng)一管理。這樣,不同的GDS系統(tǒng)都抽象成了資源池里面的一組相同的Node節(jié)點(diǎn)。
那么它具體如何運(yùn)轉(zhuǎn)的呢?
當(dāng)緩存系統(tǒng)相關(guān)航班數(shù)據(jù)過(guò)期后,前臺(tái)搜索告知MQ有實(shí)時(shí)搜索任務(wù),MQ統(tǒng)一把異步任務(wù)交給Router,這個(gè)時(shí)候Router并不會(huì)直接請(qǐng)求GDS數(shù)據(jù),而是去找Node池。Node池會(huì)動(dòng)態(tài)分配一個(gè)Node節(jié)點(diǎn)給Router,最后Router查找Node節(jié)點(diǎn)映射的GDS,然后去請(qǐng)求數(shù)據(jù),最后異步更新對(duì)應(yīng)的緩存數(shù)據(jù)。通過(guò)技術(shù)的實(shí)現(xiàn),我們把哪些不穩(wěn)定的,甚至半癱瘓的GDS充分利用了起來(lái)(包含付費(fèi)的一種黑屏終端,我們把它用成了免費(fèi)模式,這里用到了某些黑科技,政策原因不方便透露),同時(shí)滿足了前臺(tái)上億次搜索查詢!
監(jiān)控系統(tǒng)
鑒于機(jī)票系統(tǒng)的復(fù)雜度和大業(yè)務(wù)量,完備監(jiān)控是很必要的:
1、整個(gè)Qunar系統(tǒng)架構(gòu)層級(jí)復(fù)雜,第三方服務(wù)調(diào)用較多(譬如GDS),早期監(jiān)控系統(tǒng)基于CACTI+NAGIOS ,CACTI有很豐富的DashBoard,可以多維度的展示監(jiān)控?cái)?shù)據(jù)。除此以外,公司為了保證核心業(yè)務(wù)快速響應(yīng),埋了很多報(bào)警閾值。而且Qunar還有一個(gè)NOC小組,是專門24小時(shí)處理線上報(bào)警:記得當(dāng)時(shí)手機(jī)每天會(huì)有各種系統(tǒng)上百條的報(bào)警短信。
當(dāng)然,我還是比較淡定了。因?yàn)橄到y(tǒng)太多,報(bào)警信息也不盡是系統(tǒng)bug,它可能是某些潛在的問(wèn)題預(yù)警,所以,系統(tǒng)監(jiān)控非常至關(guān)重要。
2、復(fù)雜系統(tǒng)來(lái)源于復(fù)雜的業(yè)務(wù),Qunar除了對(duì)服務(wù)器CPU、內(nèi)存、IO系統(tǒng)監(jiān)控以外,遠(yuǎn)遠(yuǎn)是不夠的。我們更關(guān)心,或者說(shuō)更容易出問(wèn)題是業(yè)務(wù)的功能缺陷。所以,為了滿足業(yè)務(wù)需要,我們當(dāng)時(shí)研發(fā)了一套業(yè)務(wù)監(jiān)控的插件,它的核心原理如下圖:
它把監(jiān)控?cái)?shù)據(jù)先保存到內(nèi)存中,內(nèi)部定時(shí)程序每分鐘上傳數(shù)據(jù)到監(jiān)控平臺(tái)。同時(shí)它作為一個(gè)Plugin,可以即插即用。接入既有的監(jiān)控系統(tǒng),它幾乎實(shí)時(shí)做到監(jiān)控,設(shè)計(jì)上也避免了性能問(wèn)題。后期,產(chǎn)品、運(yùn)營(yíng)還基于此系統(tǒng),做數(shù)據(jù)分析和預(yù)測(cè):比如統(tǒng)計(jì)出票正態(tài)分布等。因?yàn)樗С肿远x統(tǒng)計(jì),有很方便DashBoard實(shí)時(shí)展示。對(duì)于整個(gè)公司業(yè)務(wù)是一個(gè)很有力的支撐。
到今天,這種設(shè)計(jì)思路還在很多監(jiān)控系統(tǒng)上看到相似的影子。
機(jī)票銷售系統(tǒng)
機(jī)票另一個(gè)重要系統(tǒng)TTS:TTS(Total Solution)模式,是去哪兒網(wǎng)自主研發(fā)的交易平臺(tái),是為航空公司、酒店在線旅游產(chǎn)品銷售系統(tǒng)。
TTS有大量商家入駐,商家會(huì)批量錄入航班價(jià)格信息。
為了減少大量商家同時(shí)錄入海量數(shù)據(jù)帶來(lái)的數(shù)據(jù)庫(kù)并發(fā)讀寫的問(wèn)題,我們會(huì)依據(jù)每個(gè)商家規(guī)模,通過(guò)數(shù)據(jù)庫(kù)動(dòng)態(tài)保存服務(wù)器IP,靈活的切換服務(wù)器達(dá)到負(fù)載均衡的效果。這里不再細(xì)說(shuō)了。
最后,回顧整個(gè)搜索架構(gòu)的設(shè)計(jì),核心思想體現(xiàn)了服務(wù)的一種解耦化。設(shè)計(jì)的系統(tǒng)雖然數(shù)量看起來(lái)很多,但是出發(fā)點(diǎn)都是把復(fù)雜的業(yè)務(wù)拆解成簡(jiǎn)單的單元,讓每一個(gè)單元專注自己的任務(wù)。這樣,每個(gè)系統(tǒng)的性能調(diào)優(yōu)和擴(kuò)展性變得容易。同時(shí),服務(wù)的解耦使整個(gè)系統(tǒng)更好維護(hù),更好支撐了業(yè)務(wù)。
重大喜訊,慧都學(xué)院將在3月底有一堂《基于圖的大數(shù)據(jù)分析》免費(fèi)公開(kāi)課,點(diǎn)擊立即報(bào)名。

標(biāo)簽:
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn