淘寶騰飛:浴火重生的巨人
開發(fā)平臺
2006年年底:阿里巴巴提出了Work at Alibaba的戰(zhàn)略,二十多個人就被拉到湖畔花園馬云的公寓里開始一個叫阿里軟件的公司創(chuàng)業(yè)。當(dāng)時對于Work at Alibaba有一個朦朦朧朧的感覺,就是要為中小企業(yè)提供一個工作平臺,但是工作平臺又需要是一個開放的平臺,因為賣家的需求是長尾的。當(dāng)時火熱的Salesforce給了阿里人一些啟示,那就是做一個支持二次開發(fā)的工作平臺,半開放式地滿足各種賣家的長尾管理需求。此時,軟件市場上就開始培養(yǎng)起uizao的一批TP(淘寶開放合作伙伴)。迄今為止,很多非常成功的TP就是從那個時候開始進(jìn)入淘寶賣家市場的。
但經(jīng)過一年的平臺建設(shè),發(fā)現(xiàn)開發(fā)者非常難利用平臺做二次開發(fā),只有阿里軟件內(nèi)部的團(tuán)隊構(gòu)建了三個不同的CRM軟件。這時候淘寶來了一個業(yè)界的技術(shù)牛人王文彬(菲青),這位淘寶新近的***架構(gòu)師找到阿里軟件的平臺架構(gòu)團(tuán)隊,談到了當(dāng)時業(yè)界還非常新穎的一種技術(shù)平臺——開放平臺。
例如緩存、CDN等優(yōu)化手段;運轉(zhuǎn)狀況監(jiān)測、功能降級、資源劣化、流控等可用性手段,自建機(jī)房、硬件組裝等成本控制手段。 因此,構(gòu)建一個互聯(lián)網(wǎng)網(wǎng)站確實是不容易的,技術(shù)含量十足,當(dāng) 然,經(jīng)營一家超市也不簡單。
高性能服務(wù)框架HSF
從超市的運維可以抽象出系統(tǒng)設(shè)計的一些思路,服務(wù)拆分之 后,如何取得我需要的服務(wù)?在“電視機(jī)”上,把每個集群能提供 的服務(wù)顯示出來。你不需要關(guān)心哪個人為你服務(wù),當(dāng)你有需要的時 候,請先看頭頂?shù)碾娨暀C(jī),它告訴你哪個服務(wù)在哪個區(qū)域。當(dāng)你直 接去這個區(qū)域的時候,系統(tǒng)會給你找到一個最快速的服務(wù)通道。
這就是HSF的設(shè)計思想,服務(wù)的提供者啟動時通過HSF框架 向ConfigServer(類似超市的電視機(jī))注冊服務(wù)信息(接口、版 本、超時時間、序列化方式等),這樣ConfigServer上面就定義 了所有可供調(diào)用的服務(wù)(同一個服務(wù)也可能有不同的版本);服 務(wù)調(diào)用者啟動的時候向ConfigServer注冊對哪些服務(wù)感興趣(接 口、版本),當(dāng)服務(wù)提供者的信息變化時,ConfigServer向相應(yīng) 的感興趣的服務(wù)調(diào)用者推送新的服務(wù)信息列表;調(diào)用者在調(diào)用時 則根據(jù)服務(wù)信息的列表直接訪問相應(yīng)的服務(wù)提供者,而無須經(jīng)過 ConfigServer。我們注意到ConfigServer并不會把服務(wù)提供者的IP地 址推送給服務(wù)的調(diào)用者,HSF框架會根據(jù)負(fù)載狀況來選擇具體的 服務(wù)器,返回結(jié)果給調(diào)用者,這不僅統(tǒng)一了服務(wù)調(diào)用的方式,也 實現(xiàn)了“軟負(fù)載均衡”。平時ConfigServer通過和服務(wù)提供者的心 跳來感應(yīng)服務(wù)提供者的存活狀態(tài)。
在HSF的支持下,服務(wù)集群對調(diào)用者來說是“統(tǒng)一”的,服 務(wù)之間是“隔離”的,這保證了服務(wù)的擴(kuò)展性和應(yīng)用的統(tǒng)一性。 再加上HSF本身能提供的“軟負(fù)載均衡;,服務(wù)層對應(yīng)用層來說 就是一片“私有云”了。
HSF框架以SAR包的方式部署到Jboss、Jetty或Tomcat下,在應(yīng) 用啟動的時候,HSF(High-Speed; Service Framework,在開發(fā)團(tuán) 隊內(nèi)部有一些人稱HSF為;好舒服;)服務(wù)隨之啟動。HSF旨在為 淘寶的應(yīng)用提供一個分布式的服務(wù)框架,HSF從分布式應(yīng)用層面 以及統(tǒng)一的發(fā)布/調(diào)用方式層面為大家提供支持,從而可以很容易 地開發(fā)分布式的應(yīng)用以及提供或使用公用功能模塊,而不用考慮 分布式領(lǐng)域中的各種細(xì)節(jié)技術(shù),例如,遠(yuǎn)程通訊、性能損耗、調(diào) 用的透明化、同步/異步調(diào)用方式的實現(xiàn)等問題。
從上圖HSF的標(biāo)志來看,它的速度是很快的。HSF是一個分 布式的標(biāo)準(zhǔn)Service方式的RPC(Remote Procedure Call Protocol, 遠(yuǎn)程過程調(diào)用協(xié)議)框架,Service的定義基于OSGI的方式,通 訊層采用TCP/IP協(xié)議。關(guān)于分布式的服務(wù)框架的理論基礎(chǔ),HSF 的作者畢玄寫了一篇博文(http://www.blogjava.net/BlueDavy/ archive/2008/01/24/177533.html),有關(guān)基于OSGI的分布式服 務(wù)框架,也有一系列的博文(http://www.blogjava.net/BlueDavy/ archive/2008/01/14/175054.html)。
從下面這個HSF監(jiān)控系統(tǒng)的截圖中可以更直觀地看到一些信 息,在兩個集群中有兩個服務(wù)器(其實有更多的,沒有全部截圖 下來)都提供com.taobao.item.service.SpuGroupService 這一服務(wù), 版本號都是1.0.0,這個服務(wù)在ConfigServer上的注冊信息中包含 超時時間、序列化方式。在后面那條信息中可看到,在展開的這 這個集群中服務(wù)有835臺機(jī)器已訂閱,這些訂閱者有淘寶的服務(wù)器(cart是購物車功能的服務(wù)器),也有hitao(淘花網(wǎng))的服務(wù)器。
HSF系統(tǒng)目前每天承擔(dān)了300億次以上的服務(wù)調(diào)用。
一些讀者可能會有一個疑問:既然淘寶的服務(wù)化是漸進(jìn)式的,那么在HSF出現(xiàn)之前,系統(tǒng)之間的調(diào)用采用什么方式呢?
這個有點“五花八門”,例如,對于類目的調(diào)用方式是: Forest打包成一個JAR包,在應(yīng)用啟動的時候裝載到內(nèi)存中,僅 這一個JAR包所占用的內(nèi)存就有800MB之多(因為淘寶的類目數(shù) 據(jù)太龐大了),對于當(dāng)時一般只有2GB內(nèi)存的開發(fā)機(jī)來說,加載 完類目信息后,機(jī)器運行速度就非常慢。對于用戶信息(UIC) 來說,一開始的調(diào)用方式是用Hessian接口。還有一些系統(tǒng)是通過 WebService、Socket甚至是HTTP請求來相互調(diào)用的。每種調(diào)用方 式都涉及各種超時、信息的加解密、參數(shù)的定義等問題,由此可見,在沒有HSF之前,系統(tǒng)之間的調(diào)用是錯綜復(fù)雜的。而隨著系 統(tǒng)拆分得越來越多,必須由一個統(tǒng)一的中間層來處理這種問題, HSF正是在這種背景下誕生的。
#p#
分布式數(shù)據(jù)訪問層TDDL
有了HSF和Notify的支持,在應(yīng)用級別中,整個淘寶網(wǎng)的系統(tǒng)可以拆分了,還有一個制約系統(tǒng)規(guī)模的更重要的因素,就是數(shù)據(jù) 庫,也必須拆分。
在第二部分中講過,淘寶很早就對數(shù)據(jù)進(jìn)行過分庫的處理, 上層系統(tǒng)連接多個數(shù)據(jù)庫,中間有一個叫做DBRoute的路由來對 數(shù)據(jù)進(jìn)行統(tǒng)一訪問。DBRoute對數(shù)據(jù)進(jìn)行多庫的操作、數(shù)據(jù)的整 合,讓上層系統(tǒng)像操作一個數(shù)據(jù)庫一樣操作多個庫。但是隨著數(shù) 據(jù)量的增長,對于庫表的分法有了更高的要求,例如,你的商品 數(shù)據(jù)到了百億級別的時候,任何一個庫都無法存放了,于是分成
2個、4個、8個、16個、32個……直到1024個、2048個。好,分成 這么多,數(shù)據(jù)能夠存放了,那怎么查詢它?這時候,數(shù)據(jù)查詢的 中間件就要能夠承擔(dān)這個重任了,它對上層來說,必須像查詢一 個數(shù)據(jù)庫一樣來查詢數(shù)據(jù),還要像查詢一個數(shù)據(jù)庫一樣快(每條 查詢在幾毫秒內(nèi)完成),TDDL就承擔(dān)了這樣一個工作。
另外,加上數(shù)據(jù)的備份、復(fù)制、主備切換等功能,這一套系 統(tǒng)都在TDDL中完成。在外面有些系統(tǒng)也用DAL(數(shù)據(jù)訪問層) 這個概念來命名這個中間件。
TDDL實現(xiàn)了下面三個主要的特性:
- 數(shù)據(jù)訪問路由——將針對數(shù)據(jù)的讀寫請求發(fā)送到最合適的 地方;
- 數(shù)據(jù)的多向非對稱復(fù)制——一次寫入,多點讀取;
- 數(shù)據(jù)存儲的自由擴(kuò)展——不再受限于單臺機(jī)器的容量瓶頸 與速度瓶頸,平滑遷移。
下圖展示了TDDL所處的位置。
下圖展示了一個簡單的分庫分表數(shù)據(jù)查詢策略。
下面是TDDL的主要開發(fā)者之一沈詢講述的“TDDL的前世今生”——數(shù)據(jù)層的發(fā)展歷程。
CommonDAO的時代
數(shù)據(jù)切分并不算是一個很新的概念,當(dāng)商品庫切分為兩個 時,就已經(jīng)出現(xiàn)了名字叫做xingdian(笑,那時候行癲已經(jīng)不寫 代碼了,但從代碼的版本信息可以看到作者)的人寫的Common DAO。CommonDAO的思路非常簡單實用,因為淘寶主要在使用 ibatis作為訪問數(shù)據(jù)庫的DAO層,所以,CommonDAO的作用就是 對ibatis層做了一個很淺的封裝,允許你通過商品字串ID的***個 字符來訪問兩臺數(shù)據(jù)庫中的一臺。
比如,如果字符串ID的***個字符是0~7,那么走到數(shù)據(jù)庫1去,如果是8~f,則走到數(shù)據(jù)庫2去。同時,也允許用戶直接給定 數(shù)據(jù)庫的名字來訪問數(shù)據(jù)庫。
這應(yīng)該是最早的數(shù)據(jù)層原型。
TDDL 1.0時代
后來,大家逐漸發(fā)現(xiàn),如果按照業(yè)務(wù)的發(fā)展規(guī)模和速度,那么使用高端存儲和小型機(jī)的Oracle存儲的成本將難以控制,于是降低成本就成了必然。
如何能夠在不影響業(yè)務(wù)正常發(fā)展的前提下,從一定程度上解決成本的問題呢?
“對一部分?jǐn)?shù)據(jù)庫使用MySQL”,DBA們的決策是這樣,于是,分布式數(shù)據(jù)層的重?fù)?dān)就落到了華黎的頭上。
別看現(xiàn)在數(shù)據(jù)水平切分似乎已經(jīng)成了基礎(chǔ)知識。在2007年、2008年,如何設(shè)計它還真是讓我們傷透了腦筋。
當(dāng)時的我們,只知道eBay有一個數(shù)據(jù)層,卻不知道如何設(shè)計和實現(xiàn)?
于是邀請了當(dāng)時所有的業(yè)務(wù)負(fù)責(zé)人來暢想數(shù)據(jù)層的樣子…… 得到了以下需求:
- 對外統(tǒng)一一切數(shù)據(jù)訪問;
- 支持緩存、文件存儲系統(tǒng);
- 能夠在Oracle和MySQL之間自由切換;
- 支持搜索引擎。
然后,我們自己的問題與現(xiàn)在大家所問的問題也是完全一樣的。
如何實現(xiàn)分布式Join(連接)?——在跨節(jié)點以后,簡單的Join會變成M×N臺機(jī)器的合并,這個代價比原來的基于數(shù)據(jù)庫的單機(jī)Join大太多了。
如何實現(xiàn)高速多維度查詢?——就像SNS中的消息系統(tǒng),A發(fā) 給B一個消息,那么A要看到的是我發(fā)給所有人的消息,而B要看 到的是所有人發(fā)給我的消息。這種多維度查詢,如何能夠做到高 效快捷呢?
#p#
如何實現(xiàn)分布式事務(wù)?——原始單機(jī)數(shù)據(jù)庫中存在著大量的 事務(wù)操作,在分布式以后,分布式事務(wù)的代價遠(yuǎn)遠(yuǎn)大于單機(jī)事 務(wù),那么這個矛盾也變得非常明顯。
華黎帶著我和念冰,坐在那里討論了一個半月,還是沒想出 來……于是決定先動起手來。名字是我起的——Taobao Distributed Data l ayer(TDDL,后來有人對它取了個外號 :“頭都大了”⊙﹏⊙b)
學(xué)習(xí)開源的Amoeba Proxy。 找到的目標(biāo)應(yīng)用是“收藏夾”,首先要做的兩個關(guān)鍵的特性是:分庫分表和異構(gòu)數(shù)據(jù)庫的數(shù)據(jù)復(fù)制。
開始本來希望和B2B的團(tuán)隊合作,因為我們覺得獨立的Proxy 沒有太大必要。而SQL解析器因為有淘寶特殊的需求,所以也需 要重寫。
可惜,***因為B2B的人搬到濱江去了,交流十分不暢,所以***只是做了拿來主義,沒有對開源的Amoeba和當(dāng)時的Cobar有所貢獻(xiàn)。
回到淘寶,因為有東西可以借鑒,我們在一個多月的時間內(nèi) 就完成了TDDL 1.0版本的工作。上線過程中雖然出了點小問題, 不過總體來說是比較成功的。
TDDL 2.0時代
隨著使用TDDL的業(yè)務(wù)越來越多,對業(yè)務(wù)方來說,DBA對于使用MySQL以及數(shù)據(jù)切分也積累了比較多的經(jīng)驗,于是決定開始 動核心應(yīng)用了。
“評價”是***個重要的應(yīng)用,評價最重要的問題還是在于雙向查詢、評價、被評價。于是我們的異構(gòu)數(shù)據(jù)源增量復(fù)制就派 上了用場。
然后是“商品”,我們在商品上投入了近半年的時間,失敗很多,也成長得最快。
- 容量規(guī)劃做得不到位,機(jī)器到位后因壓力過大,直接死掉,于是產(chǎn)生了數(shù)據(jù)庫容量線上壓力模擬測試。
- 歷史遺留問題,商品幾乎是所有的業(yè)務(wù)都會使用的資源, 所以接口設(shè)計比較復(fù)雜。很多接口的調(diào)用在新架構(gòu)上很難以低成本的方式實現(xiàn)。而推動業(yè)務(wù)改動,則需要大量的時
- 間和成本。
- 數(shù)據(jù)層代碼被業(yè)務(wù)代碼侵染,看起來似乎應(yīng)該是數(shù)據(jù)層的 代碼,但實際上又只有商品在使用。這種問題讓數(shù)據(jù)層的依賴變得更加龐大,邊緣代碼變得更多,沖突更明顯。
TDDL 3.0~TDDL 4.0時代
在商品之后,似乎所有的應(yīng)用都可以使用類似的方式來解決 業(yè)務(wù)增長上量的問題。但正當(dāng)我們志得意滿的時候,卻被“交 易”撞了一個滿懷。
我一直很感謝交易線的所有同仁,他們是淘寶草根精神的典 型代表 —— 功能可以做得不那么“漂亮”,但必須減少中間環(huán) 節(jié),真正做到了實用、干凈、簡潔。我們在向他們介紹產(chǎn)品的時 候,他們對我們的實現(xiàn)細(xì)節(jié)提出了非常多的質(zhì)疑,他們認(rèn)為整個 流程中只有規(guī)則、主備切換對他們是有意義的,而解析、合并則 是他們所不需要的功能。
“不需要的功能為什么要放到流程里?增加的復(fù)雜度會導(dǎo)致 更多的問題”。在當(dāng)時,我感到很痛苦,因為我無法回答他們這 些質(zhì)疑之聲。
不過,也正是因為這些質(zhì)疑,讓我有了一個契機(jī),重新審視自己所創(chuàng)造出來的產(chǎn)品。
我問自己:它能夠給業(yè)務(wù)帶來什么益處? 對此,我的回答是:
- 規(guī)則引擎/切分規(guī)則可以用配置的方式幫助業(yè)務(wù)隔離具體的 數(shù)據(jù)庫地址與用戶的業(yè)務(wù)邏輯;
- 單機(jī)主備切換;
- 數(shù)據(jù)源簡化和管理。
于是,我們就產(chǎn)生了TDDL 3.0版本。其主要的作用就是將代 碼做了邏輯切分,將單機(jī)主備切換和數(shù)據(jù)源管理獨立了出來。這 樣,可以針對不同的業(yè)務(wù)需求,給予不同的邏輯分層。讓每一個 業(yè)務(wù)都有適合自己的使用數(shù)據(jù)庫的方式。
同時,我們開始做工具,Rtools/JADE 作為數(shù)據(jù)庫運維平臺的 組件被提了出來。在它的幫助下,我們發(fā)現(xiàn)能夠極大地提升用戶 在使用單機(jī)數(shù)據(jù)源和多機(jī)數(shù)據(jù)源時的效率。用戶只需要在客戶端 給定兩個屬性,就可以立刻開始使用。結(jié)果是用戶反饋比以前好了很多。
這也堅定了我們開發(fā)工具的決心。
工具平臺時代
在嘗到工具平臺的甜頭以后,我們在工具組件上走得更遠(yuǎn)了。
首先被提出的是“愚公”數(shù)據(jù)遷移平臺。該平臺能夠在多種 異構(gòu)的數(shù)據(jù)庫中進(jìn)行數(shù)據(jù)的平滑移動,對業(yè)務(wù)影響很小,并且也 允許業(yè)務(wù)插入自己的業(yè)務(wù)邏輯。
這個東西主要能夠幫助業(yè)務(wù)進(jìn)行數(shù)據(jù)庫自動擴(kuò)容,自動縮 容,單機(jī)、多機(jī)數(shù)據(jù)遷移,在Oracle到MySQL數(shù)據(jù)遷移等場景中 都發(fā)揮了重要的作用。
然后,又以內(nèi)部開源的方式提出了“精衛(wèi)”數(shù)據(jù)增量復(fù)制 平臺。這個平臺基于數(shù)據(jù)庫的通用數(shù)據(jù)分發(fā)組件,基于開源的Tungsten進(jìn)行了大量Bug Fix和結(jié)構(gòu)調(diào)優(yōu)。在數(shù)據(jù)的一對多分發(fā)以 及異步通知給DW和搜索等場景中都發(fā)揮了重要的作用。
TDDL的現(xiàn)在
粗略統(tǒng)計下來,TDDL已經(jīng)走過了4年的時間,滿足了近700個 業(yè)務(wù)應(yīng)用的使用需求。其中有交易商品評價用戶等核心數(shù)據(jù),也有不那么有名的中小型應(yīng)用。量變產(chǎn)生質(zhì)變,如何能夠更好地幫 助這些業(yè)務(wù)以更低的成本更快地完成業(yè)務(wù)需求,將成為數(shù)據(jù)層未 來最重要的挑戰(zhàn)。