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