淘寶的起源故事、技術發展之路 - 2013

淘寶創造的紀錄, 詳見: 淘寶 1111 光棍節 創造的紀錄

淘寶是如何創造這種記錄的? 技術架構? 歷史演進 是如何呢? 先看看淘寶的架構、經驗, 再來看淘寶的歷史、技術發展的過程.

淘寶的架構、說明

淘寶 Open Source Project

再來要開始講故事了~

淘寶的起源故事、技術發展之路

淘寶的歷史、技術發展之路, 下述摘錄自這幾篇文章:

  1. 淘寶技術發展(引言)
  2. 淘寶技術發展 (個人網站)
  3. 淘寶技術發展 (Oracle/支付寶/旺旺)
  4. 淘寶技術發展 (Java時代:脫胎換骨)
  5. 淘寶技術發展 (Java時代:堅若磐石)
  6. 淘寶技術發展 (Java時代:創造技術-TFS)
  7. 淘寶技術發展 (分散式時代:服務化)
  8. 淘寶的起源故事
  9. 淘寶技術發展之路
  10. 註: 原本看到的文章不見了, 花時間把整篇文章找齊了, 所以下述完整轉載備份:

淘寶網的起源故事

2003 年 4 月 7 日,馬雲,在杭州,成立了一個神秘的組織。他叫來十位員工,要他們簽了一份協議,這份協議要求他們立刻離開阿里巴巴,去做一個神秘的項目。這個項目要求絕對保密,老馬戲稱“連說夢話被老婆聽到都不行,誰要是透漏出去,我將追殺到天涯海角”。這份協議是英文版的,匆忙之間,大多數人根本來不及看懂,但出于對老馬的信任,都卷起鋪蓋離開了阿里巴巴。

他們去了一個神秘的據點 —— 湖畔花園小區的一套未裝修的房子裏,房子的主人是馬雲。這夥人剛進去的時候,馬雲給他們布置了一個任務,就是在最短的時間內做出一個個人對個人(C2C)的商品交易的網站。現在出一個問題考考讀者,看你適不適合做淘寶的創業團隊。親,要是讓你來做,你怎麼做?

在說出這個答案之前,容我先賣個關子,介紹一下這個創業團隊的成員:三個開發工程師(虛竹、三豐、多隆)、一個UED(二當家)、三個運營(小寶、阿珂、破天)、一個經理(財神)、還有就是馬雲和他的秘書。當時對整個項目組來說壓力最大的就是時間,怎麼在最短的時間內把一個從來就沒有的網站從零開始建立起來?瞭解淘寶歷史的人知道淘寶是在 2003 年 5 月 10 日上線的,這之間只有一個月。要是你在這個團隊裏,你怎麼做?我們的答案就是:買一個來。

淘寶技術發展之路

一、引言

光棍節的狂歡

“時間到,開搶!”坐在電腦前早已等待多時的小美一看時間已到 2011 年 11 月 11 日零時,便迫不及待地投身於淘寶商城一年一度的大型網購促銷活動 —— “淘寶雙11購物狂歡節”。小美打開早已收藏好的寶貝 —— 某品牌的雪地靴,飛快的點擊購買,付款,一回頭發現 3000 雙靴子已被搶購一空。
小美跳起來,大叫一聲“歐耶!”
小美不知道,就在 11 日零點過後的這一分钟內,全國有 342 萬人和她一起涌入淘寶商城。當然,她更不知道,此時此刻,在淘寶杭州的一間辦公室裏,燈火通明,這裏是“戰時指揮部”,淘寶技術部的一群工程師,正在緊盯着網站的流量和交易資料。白板上是他們剛剛下的注,賭誰能最准確地猜中流量峰值和全天的交易總額。他們的手邊放着充足的食物和各類提神的飲料。
一陣急促的電話聲響起來,是前線部門詢問資料的,工程師大聲報着:“第 1 分钟,進入淘寶商城的會員有 342 萬”。過一會工程師主動拿起電話:“交易額超過 1 億了,現在是第 8 分钟。”接下來,“第 21 分钟,剛突破 2 億”。“第 32 分钟,3 億了”。“第 1 個小時,4.39 億”。這些資料隨後出現在微博上,引起一片驚呼。
“完蛋了!”突然有人大喝一聲,所有的眼睛都緊張的盯着他,只見他撓撓頭,嘿嘿的笑道“我賭的少了,20 億輕松就能過了,我再加 5 億”,他跑去白板邊上把自己的賭注擦去,寫上 25,接下來有人寫上 28,有人寫上 30,有人跑到微博上開下盤口,同事們紛紛轉載下注。接下來的這 24 個小時,戰時指揮部的工程師們都不能休息,他們盯着網站的各種監控指標,適時的調整機器和增減功能。頂住第一波高峰之後,這些人開始忙裏偷閑的给自己買東西,大家互相交流着哪家買的移動硬碟靠譜,哪家衣服適合自己的女朋友,不時的有人哀嚎寶貝被人搶了、信用卡額度不夠了。同時,旁邊白板上的賭注越下越大。

11 月 11 日,這個棍子最多的日子被網民自我調侃的變成了一個節日 —— “光棍節”。而淘寶網又用瘋狂的折扣促銷给它賦予了另外一個意義 —— “購物狂歡節”。2011 年 11 月 11 日這一天,淘寶商城與淘寶網交易額之和突破 52 億,這個數字是“購物天堂”香港一天零售總額 8.5 億的 6 倍。

網民感受到的是瘋搶的喜悅,而網站的技術人員感受到的卻是“壓力山大”。就如同你家辦酒席,宴請左鄰右舍,這個辦起來容易。倘若宴請十裏八鄉所有的人,吃飯的人自然開心,但卻不是一般人家能夠辦得起來的。能辦得起來如此盛宴者,需要強大的財力物力、組織能力、技術實力(例如做這麼多菜,你的炒鍋一定要是“分散式的”、“可複製的”、“可擴展的”,洗菜切菜要有“工作流引擎”,上菜的路徑要用圖論來計算出來,甚至連厨房的下水道都要重新設計)。

淘寶能夠舉辦如此盛宴,網站的技術實力可見一斑。淘寶網擁有全國最大的 Hadoop 分散式計算集群之一,日新增資料 50TB,有 40PB 海量資料存儲。分布在全國各地 80 多個節點的 CDN 網络,支持的流量超過 800Gbps。淘寶的搜索引擎能夠對數十億的商品資料進行實時搜索,另外還擁有自主研發的文件存儲系統和緩存系統,以及 Java 中間件和消息中間件系統,這一切組成了一個龐大的電子商務操作系統。另外從商業資料上來看,Amazon 的財報顯示 2011 年完成了大約 480 億美金的交易額,eBay 2011 年財報全年完成了大約 600 億美金的交易額(不包括其獨立的汽車交易平台)。不管從交易額、商品數量、同比增速等指標上看,淘寶網均遠超於此,是目前全球最大的電子商務平台。(由於淘寶非上市公司,未公布2011年業績,以上內容來自淘寶網技術副總裁@_行癲 的微博)

以上這些技術資料可能已經讓一些同學產生不適的感覺,为了讓更多的人讀懂這本書,我們從技術的角度來看,小美訪問淘寶網的時候,網站上發生了什麼事情。参考資料:《技術普及帖:你剛才在淘寶上買了一件東西》,來自南京郵電大學孫放同學。

为了有個更直觀的對比,我們說一個同行,他在 2011 年光棍節之前做促銷,流量上去之後,達到 12Gbps(他們有這麼大的流量,老板很高興,在微博上面說了這個資料),這時候流量達到了極限,網站幾乎掛掉,用戶無法下訂單。而淘寶網光棍節當天網络的流量最高達到 800多Gbps,帶给各家銀行和快遞公司的流量也讓他們壓力山大,如臨大敵(後來,他們以能夠撐住淘寶帶來的流量为榮而到處宣傳)。另外如果你在網上購買過火車票的話,更能體會到網站能支持多大的流量有多重要。但這不是一朝一夕做出來的,也不是有錢就能辦到的。

以上對比的這些網站,也許讀者很容易就猜到是哪一家,這裏拿出來作對比,絕對沒有嘲笑人家的意思,采用通常的網站技術方案,能做到這種程度已經不錯了。任何網站的發展都不是一蹴而就的,在什麼樣的階段采用什麼樣的技術。在發展的過程中網站會遇到各種各樣的問題和業務帶來的壓力,正是這些原因才推動着技術的進步和發展,而技術的發展又會反過來促進業務的更大提升。二者互为因果,相互促進。如今淘寶網的流量已經是全球排名第12、國內排名第3(美國的 eBay 全球排名23,國內前兩名是百度和騰訊)。淘寶網的系統也從使用一台服務器,到采用萬台以上的服務器。本書就为大家描述淘寶網在整個發展過程中,所有的主動和被動的技術變革的前因後果,這由很多有趣的故事組成。

正如同很多人或組織成功了以後,就會为自己的出身編造一個美麗的傳說。淘寶網的出身,網上也有非常多的傳說,下面我們就從它的出生開始講起。

二、個人網站

2003 年 4 月 7 日,馬雲,在杭州,成立了一個神秘的組織。他叫來十位員工,要他們簽了一份協議,這份協議要求他們立刻離開阿裏巴巴,去做一個神秘的項目。這個項目要求絕對保密,老馬戲稱“連說夢話被老婆聽到都不行,誰要是透漏出去,我將追殺到天涯海角”。這份協議是英文版的,匆忙之間,大多數人根本來不及看懂,但出于對老馬的信任,都卷起鋪蓋離開了阿裏巴巴。

他們去了一個神秘的據點 —— 湖畔花園小區的一套未裝修的房子裏,房子的主人是馬雲。這夥人剛進去的時候,馬雲給他們布置了一個任務,就是在最短的時間內做出一個個人對個人(C2C)的商品交易的網站。現在出一個問題考考讀者,看你適不適合做淘寶的創業團隊。親,要是讓你來做,你怎麼做?

在說出這個答案之前,容我先賣個關子,介紹一下這個創業團隊的成員:三個開發工程師(虛竹、三豐、多隆)、一個UED(二當家)、三個運營(小寶、阿珂、破天)、一個經理(財神)、還有就是馬雲和他的秘書。當時對整個項目組來說壓力最大的就是時間,怎麼在最短的時間內把一個從來就沒有的網站從零開始建立起來?瞭解淘寶曆史的人知道淘寶是在 2003 年 5 月 10 日上線的,這之間只有一個月。要是你在這個團隊裏,你怎麼做?我們的答案就是:買一個來。

買一個網站顯然比做一個網站要省事一些,但是他們的夢想可不是做一個小網站而已,要做大,就不是隨便買個就行的,要有比較低的維護成本,要能夠方便的擴展和二次開發。那接下來就是第二個問題:買一個什麼樣的網站?答案是:輕量一點的,簡單一點的,於是買了這樣一個架構的網站:LAMP(Linux+Apache+MySQL+PHP)。這個直到現在還是一個很常用的網站架構模型。這種架構的優點是:無需編譯,發布快速,PHP功能強大,能做從頁面渲染到資料訪問所有的事情,而且用到的技術都是開源的,免費。

當時我們是從一個美國人那裏買來的一個網站系統,這個系統的名字叫做 PHPAuction(他們的官方網站 http://www.phpauction.net,這個名字很直白,一眼就看出來這個系統是用什麼語言做的、是幹什麼用的),PHPAuction有好幾個版本,我們買的是最高版的,功能比較多,而且最重要的是對方提供了源代碼。最高版比較貴,花了我們 2000 美金(貌似現在降價了,只要 946 美元)。買來之後不是直接就能用的,需要很多本地化的修改,例如頁面模板改的漂亮一點,頁頭頁腳加上自己的站點簡介等,其中最有技術含量的是對資料庫進行了一個修改。原來是從一個資料庫進行所有的讀寫操作,拿過來之後多隆把它给拆分成一個主庫、兩個從庫,讀寫分離。這麼做的好處有幾點:存儲容量增加了,有了備份,使得安全性增加了,讀寫分離使得讀寫效率提升了。這樣整個系統的架構就如下圖所示:

淘寶系統架構
淘寶系統架構

其中 Pear DB 是一個 PHP 模塊,負責資料訪問層。另外也用開源的論壇系統 PHPBB(http://www.phpbbchina.com )搭建了一個小的論壇社區,虛竹負責機器采購、配置、架設等,三豐和多隆負責編碼,他們把交易系統和論壇系統的用戶信息打通,给運營人員開發出後台管理(admin系統)的功能,把交易類型從只有拍賣這一種增加为拍賣、一口價、求購商品、海報商品(意思是還沒推出的商品,先掛個海報出來)這四種。(PHPAuction 只有拍賣的交易,Auction 即拍賣的意思。@_行癲在微博中提到:今天 eBay 所有交易中拍賣交易仍然占了 40%,而在中國,此種模式在淘寶幾乎從一開始就未能占據優勢,如今在主流的交易中幾乎可以忽略不計。背後的原因一直令人費解。我大致可以给出其中一種解釋,eBay 基本在發達國家展開業務,制造業外包後,電子商務的基本群體大多只能表現为零散的個體間交易。)

在經歷了另外一些有趣的事情之後(這些有趣的事情包括“淘寶”這個名字的由來,由於本書主要描述技術方面的故事,對這些有興趣的可以去網上找),網站開始上線運行了。

淘寶首頁
淘寶首頁

在接下來的大半年時間裏,這個網站迅速顯示出了它的生機。這裏有必要提一下當時的市場環境,非典(SARS)的肆虐使得大家都不敢出門,尤其是去商場之類人多的地方。另外在神州大地上最早出現的 C2C 網站易趣也正忙的不亦樂乎,2002 年 3 月,eBay 以 3000 萬美元收購了易趣公司 33% 的股份,2003 年 6 月以 1.5 億美元收購了易趣公司剩餘 67% 的股份。當時淘寶網允許買賣雙方留下聯系方式,允許同城交易,整個操作過程簡單輕松。而 eBay 为了收取交易傭金,是禁止這麼做的,這必然增加了交易過程的難度。而且 eBay 为了全球統一,把易趣原來的系統替換成了美國 eBay 的系統,用戶體驗一下子全變了,操作起來非常麻煩,這等於是把積累的用戶拱手送给了淘寶。为了不引起 eBay 的注意,淘寶網在 2003 年裏一直聲稱自己是一個“個人網站”。由於這個創業團隊強大的市場開拓和運營能力,淘寶網發展的非常迅猛,2003 年底就吸引了注冊用戶XXX,最高每日 31 萬PV,從 5 月到年底成交額 4000 萬。這沒有引起 eBay 的注意,卻引起了阿裏巴巴內部很多員工的注意,他們覺得這個網站以後會成为阿裏巴巴強勁的對手。甚至有人在內網發帖,忠告管理層要警惕這個剛剛起步的網站,但管理層似乎無動於衷。(這個團隊的保密工作做的真好)

在市場和運營的後方,淘寶網的技術團隊也在快速的做着系統的改進和創新。這裏還有個有趣的故事,eBay 和易趣早期都有員工在論壇上響應用戶的需求,eBay 的論壇用粉紅色背景來區分員工的發言,易趣的員工在論壇上昵稱都選各種豆豆,例如黃豆豆、蠶豆豆等。淘寶在討論運營策略的時候提到這個問題,要求所有的員工都去論壇上回答用戶的問題。最早回答問題的任務落在小寶頭上,那我們用什麼名字好呢?“淘淘”?“寶寶”?小寶都不滿意,太女性化了。討論了很久之後,小寶靈光乍現,幹脆取個名字叫“小寶”吧,小寶帶七個老婆來開店,迎接各位客官,很有故事性。於是很多武俠小說中的人物開始在論壇中行俠仗義,這些昵稱下面標志着“淘寶店小二”,他們回答着各種各樣的問題,快速響應着用戶的各種需求。如果是技術上能解决的,幾個人商量一下,馬上就開發、測試、發布上線。反過來對比一下,易趣被 eBay 收購之後,系統更換成了全球通用的版本,響應用戶的一個需求需要層層審批,反應速度自然慢了下來。

當時淘寶第一個版本的系統裏面已經包含了商品發布、管理、搜索、商品詳情、出價購買、評價投訴、我的淘寶這些功能(現在主流程中也是這些模塊。在 2003 年 10 月增加了一個功能節點:“安全交易”,這個是支付寶的雛形)。隨着用戶需求和流量的不斷增長,系統上面做了很多的日常改進,服務器由最初的一台變成了三台,一台負責發送 email、一台負責運行資料庫、一台負責運行 web App。過一段時間之後,商品搜索的功能占用資料庫資源太大了(用like搜索的,很慢),又從阿裏巴巴中文站搬過來他們的搜索引擎 iSearch,起初 iSearch 索引的文件放在硬碟上,隨着資料量的增長,又采購了 NetApp 服務器放置 iSearch。

如此快節奏的工作,其實大家都累得不行,有人就提議大家隨時隨地的鍛煉身體,可是外面 SARS 橫行,在一個一百多方的房子裏,怎麼鍛煉呢?高挑美女阿珂提議大家練習提臀操,這個建議遭到男士的一致反對,後來虛竹就教大家練習倒立,這個大家都能接受。於是這個倒立的傳統一直延續至今,和花名文化、武俠文化一並傳承了下來。

隨着訪問量和資料量的飛速上漲,問題很快就出來了,第一個問題出現在資料庫上。MySQL 當時是第 4 版的,我們用的是默認的存儲引擎 MyISAM,這種類型讀資料的時候會把表鎖住(我們知道 Oracle 在寫資料的時候會有行鎖,讀資料的時候是沒有的),尤其是主庫往從庫上面寫資料的時候,會對主庫產生大量的讀操作,使得主庫性能急劇下降。這樣在高訪問量的時候,資料庫撐不住了。另外,當年的 MySQL 不比如今的 MySQL,在資料的容量和安全性方面也有很多先天的不足(和 Oracle 相比)。

三、Oracle/支付寶/旺旺

淘寶網作为個人網站發展的時間其實並不長,由於它太引人注目了,馬雲在 2003 年 7 月就宣布了這個是阿裏巴巴旗下的網站,隨後在市場上展開了很成功的運作。最著名的就是利用中小網站來做廣告,突圍 eBay 在門戶網站上對淘寶的廣告封鎖。上網比較早的人應該還記得那些在右下角的彈窗和網站腰封上一閃一閃的廣告。市場部那位到處花錢買廣告的家夥,太能花錢了,一出手就是幾百萬,他被我們稱为“大少爺”。

“大少爺”們做的廣告,帶來的就是迅速上漲的流量和交易量。在 2003 年底,MySQL 已經撐不住了,技術的替代方案非常簡單,就是換成 Oracle。換 Oracle 的原因除了它容量大、穩定、安全、性能高之外,還有人才方面的原因。在 2003 年的時候,阿裏巴巴已經有一支很強大的 DBA 團隊了,有馮春培、汪海(七公)這樣的人物,後來還有馮大輝(@fenng)、陳吉平(拖雷)。這樣的人物牛到什麼程度呢?Oracle 给全球的技術專家頒發一些頭銜,其中最高級別的叫 ACE(就是撲克牌的“尖兒”,夠大的吧),被授予這個頭銜的人目前全球也只有 300 多名(名單在這裏: http://go.rritw.com/apex.oracle.com/pls/otn/f?p=19297:3 ),當年全球只有十幾名。有如此強大的技術後盾,把 MySQL 換成 Oracle 是順理成章的事情。

但更換資料庫不是只換個庫就可以的,訪問方式,SQL 語法都要跟着變,最重要的一點是,Oracle 並發訪問能力之所以如此強大,有一個關鍵性的設計 —— 連接池。但對於 PHP 語言來說它是放在 Apache 上的,每一個請求都會對資料庫產生一個連接,它沒有連接池這種功能(Java 語言有 Servlet 容器,可以存放連接池)。那如何是好呢?這幫人打探到 eBay 在 PHP 下面用了一個連接池的工具,是 BEA 賣给他們的。我們知道 BEA 的東西都很貴,我們買不起,於是多隆在網上尋尋覓覓,找到一個開源的連接池代理服務 SQLRelay( http://sourceforge.jp/projects/freshmeat_sqlrelay ),這個東西能夠提供連接池的功能,多隆對它進行了一些功能改進之後就拿來用了。這樣系統的架構就變成了如下的樣子:

系統架構 - Oracle
系統架構 - Oracle

資料一開始是放在本地的,DBA 們對 Oracle 做調優的工作,也對 SQL 進行調優。後來資料量變大了,本地存儲不行了。買了 NAS(Network Attached Storage:網络附屬存儲),NetApp 的 NAS 存儲作为了資料庫的存儲設備,加上 Oracle RAC(Real Application Clusters,實時應用集群)來實現負載均衡。七公說這實際上是走了一段彎路,NAS 的 NFS(Network File System)協議傳輸的延遲很嚴重,但那時侯不懂。後來采購了 Dell 和 EMC 合作的 SAN 低端存儲,性能一下子提升了 10 幾倍,這才比較穩定了。再往後來資料量更大了,存儲的節點一拆二、二拆四,RAC 又出問題了。這才踏上了購買小型機的道路。在那段不穩定的時間裏,七公曾經在機房住了 5 天 5 夜。

替換完資料庫,時間到了 2004 年春天,俗話說“春宵一刻值千金”,但這些人的春宵卻不太好過了。他們在把資料的連接放在 SQLRelay 之後就噩夢不斷,這個代理服務經常會死鎖,如同之前的 MySQL 死鎖一樣。雖然多隆做了很多修改,但當時那個版本內部處理的邏輯不對,問題很多,唯一解决的辦法就是“重啟”它的服務。這在白天還好,連接上機房的服務器,把進程殺掉,然後開启就可以了,但是最痛苦的是它在晚上也要死掉,於是工程師們不得不 24 小時開着手機,一旦收到“ SQLRelay 進程掛起”的短信,就從春夢中醒來,打開電腦,連上機房,重啟服務。後來幹脆每天睡覺之前先重啟一下。做這事最多的據說是三豐,他現在是淘寶網的總裁。現在我們知道,任何牛B的人物,都有一段苦B的經歷。

微博上有人說“好的架構是進化來的,不是設計來的”。的確如此,其實還可以再加上一句“好的功能也是進化來的,不是設計來的”。在架構的進化過程中,業務的進化也非常迅猛。最早的時候,買家打錢给賣家都是通過銀行轉帳匯款,有些騙子收了錢卻不發貨,這是一個很嚴重的問題。然後這夥人研究了 PayPal 的支付方式,發現也不能解决問題。後來這幾個聰明的腦袋又想到了“擔保交易”這種第三方托管資金的辦法。於是在 2003 年 10 月,淘寶網上面上線了一個功能,叫做“安全交易”,賣家選擇支持這種功能的話,買家會把錢交给淘寶網,等他收到貨之後,淘寶網再把錢给賣家。這就是現在的支付寶,在前兩天(2012.2.21)年會上,支付寶公布 2011 年的交易筆數已經是 PayPal 的兩倍。這個劃時代的創新,其實就是在不斷的思索過程中的一個靈光乍現。

當時開發“安全交易”功能的是茅十八和他的徒弟苗人鳳(茅十八開發到一半去上海讀 MBA 去了,苗人鳳現在是支付寶的首席業務架構師),開發跟銀行網關對接的功能的是多隆。當時多數銀行的網站已經支持在線支付了,但多隆告訴我,他們的網關五花八門,用什麼技術的都有,必須一家一家去接。而且他們不保證用戶付錢了就一定扣款成功、不保證扣款成功了就一定通知淘寶、不保證通知淘寶了就一定能通知到、不保證通知到了就不重复通知。這害苦了苗人鳳,他必須每天手工核對帳單,對不齊的話就一定是有人的錢找不到地方了,少一分錢都睡不着覺。另外他为了測試這些功能,去杭州所有的銀行都辦理了一張銀行卡。一堆銀行卡擺在桌子上,不知道的人還以为這個家夥一定很有錢,其實裏面都只是十塊八塊的。現在我們再一次知道,任何牛B的人物,都必須有一段苦B的經歷。

有人說淘寶打敗易趣(eBay 中國)是靠免費,其實這只是原因之一。如果說和易趣過招第一招是免費的話,這讓用戶沒有門檻就願意來,那第二招就是“安全支付”,這讓用戶放心付款,不必擔心被騙。在武俠小說中真正的高手飛花摘葉即可傷人,他們不會局限於一招兩招,一旦出手,連綿不絕。而淘寶的第三招就是“旺旺”,讓用戶在線溝通。其實淘寶旺旺也不是自己生出來的,是從阿裏巴巴的“貿易通”複製過來的。從 2004 年 3 月開始,“叮咚、叮咚”這個經典的聲音就回蕩在所有淘寶買家和賣家的耳邊,“親,包郵不?”,“親,把零頭去掉行不?”,這親切的砍價聲造就了後來的“淘寶體”。有人說中國人就是愛砍價,雖然筆者體會不到砍價成功後有多少成就感,但每次我去菜市場,看到大媽們砍價砍得天昏地暗,那滿足的勁頭堪比捡到了錢,我就深刻的理解了淘寶旺旺在交易過程中的價值。我猜 eBay 也體會不到砍價的樂趣,他們一直不允許買賣雙方在線聊天,收購了 skype 之後也沒有用到電子商務中去。

旺旺在推出來沒多久,就惹了一個法律方面的麻煩。有個做雪餅的廠家找上門來,說我們侵權了,他們家的雪餅很好吃,牛奶也做得不錯,我們都很喜歡。然後我們就在旺旺的前面加了兩個字,叫做“淘寶旺旺”。在那個野蠻生長的階段,其實很多產品都是想到什麼就做什麼,例如我們還搭建過一個聊天室,但似乎淘寶網不是一個閑聊的地方,這個聊天室門可罗雀,一段時間後就關閉掉了。

SQLRelay 的問題搞得三豐他們很難睡個囫囵覺,那一年開半年會的時候,公司特地给三豐頒了一個獎項,對他表示深切的安慰。但不能總這樣啊,於是,2004 年的上半年開始,整個網站就開始了一個脫胎換骨的手術。

四、淘寶技術發展(Java時代:脫胎換骨)

我的師父黃裳@嶽旭強曾經說過,“好的架構圖充滿美感”,一個架構好不好,從審美的角度就能看得出來。後來我看了很多系統的架構,發現這個言論基本成立。那麼反觀淘寶前面的兩個版本的架構,你看哪個比較美?

系統架構 Oracle
系統架構 MySQL
系統架構 Oracle
系統架構 Oracle

顯然第一個比較好看,後面那個顯得頭重腳輕,這也注定了它不是一個穩定的版本,只存活了不到半年的時間。2004 年初,SQL Relay 的問題解决不了,資料庫必須要用 Oracle,那從哪裏動刀?只有換開發語言了。換什麼語言好呢?Java。Java 是當時最成熟的網站開發語言,它有比較良好的企業開發框架,被世界上主流的大規模網站普遍采用,另外有 Java 開發經驗的人才也比較多,後續維護成本會比較低。

到 2004 年上半年,淘寶網已經運行了一年的時間,這一年積累了大量的用戶,也快速的開發了很多功能,當時這個網站已經很龐大了,而且新的需求還在源源不斷的過來。把一個龐大的網站的開發語言換掉,無異於脫胎換骨,在換的過程中還不能拖慢業務的發展,這無異於邊換邊跑,對時間和技術能力的要求都非常高。做這樣的手術,需要請第一流的專家來主刀。現在再考一下讀者,如果你在這個創業團隊裏面,請什麼樣的人來做這事?我們的答案是請 Sun 的人。沒錯,就是創造 Java 語言的那家公司,世界上沒有比他們更懂 Java 的了。除此之外,還有一個不为人知的原因,……(此處和諧掉 200 字,完整版見 aliway)

這幫 Sun 的工程師的確很強大,在筆者 2004 年底來淘寶的時候,他們還在,有幸跟他們共事了幾個月。現在擺在他們面前的問題是用什麼辦法把一個龐大的網站從 PHP 語言遷移到 Java?而且要求在遷移的過程中,不停止服務,原來系統的 bugfix 和功能改進不受影響。親,你要是架構師,你怎麼做?有人的答案是寫一個翻譯器,如同把中文翻譯成英文一樣,自動翻譯。我只能說你這個想法太超前了,換個說法就是“too simple, sometimes naive”。當時沒有,現在也沒有人能做到。他們的大致方案是给業務分模塊,一個模塊一個模塊的替換。如用戶模塊,老的 member.taobao.com 繼續維護,不添加新功能,新的功能先在新的模塊上開發,跟老的共用一個資料庫,開發完畢之後放到不同的應用集群上,另開個域名 member1.taobao.com,同時替換老的功能,替換一個,把老的模塊上的功能關閉一個,逐漸的把用戶引導到 member1.taobao.com,等所有功能都替換完畢之後,關閉 member.taobao.com。後來很長時間裏面都是在用 member1 這樣奇怪的域名,兩年後有另外一家互聯網公司開始做電子商務了,我們發現他們的域名也叫 member1.xx.com、auction1.xx.com……

說了開發模式,再說說用到的 Java MVC 框架,當時的 Struts 1.x 是用的比較多的框架,但是用過 WebWork 和 Struts 2 的同學可能知道,Struts 1.x 在多人協作方面有很多致命的弱點,由於沒有一個輕量框架作为基礎,因此很難擴展,這樣架構師對於基礎功能和全局功能的控制就很難做到。而阿裏巴巴的 18 個創始人之中,有個架構師,在 Jakarta Turbine 的基礎上,做了很多擴展,打造了一個阿裏巴巴自己用的 MVC 框架 WebX (http://go.rritw.com/www.openwebx.org/docs/Webx3_Guide_Book.html),這個框架易於擴展,方便組件化開發,它的頁面模板支持 JSP 和 Velocity 等、持久層支持 iBATIS 和 Hibernate 等、控制層可以用 EJB 和 Spring(Spring 是後來才有的)。項目組選擇了這個強大的框架,這個框架如果當時開源了,也許就沒有 WebWork 和 Struts 2 什麼事了。另外,當時 Sun 在全世界大力推廣他們的 EJB,雖然淘寶的架構師認为這個東東用不到,但他們還是極力堅持。在經歷了很多次的技術討論、爭論和爭吵之後,這個系統的架構就變成了下圖的樣子:

Oracle 讀寫架構

Java 應用服務器是 Weblogic,MVC 框架是 WebX、控制層用了 EJB、持久層是 iBATIS,另外为了緩解資料庫的壓力,商品查詢和店鋪查詢放在搜索引擎上面。這個架構圖是不是好看了一點了,親?

這幫 Sun 的工程師開發完淘寶的網站之後,又做了一個很牛的網站,叫“支付寶”。

其實在任何時候,開發語言本身都不是系統的瓶頸,業務帶來的壓力更多的是壓到了資料和存儲上。上面一篇也說到,MySQL 撐不住了之後換 Oracle,Oracle 的存儲一開始在本機上,後來在 NAS 上,NAS 撐不住了用 EMC 的 SAN 存儲,再然後 Oracle 的 RAC 撐不住了,資料的存儲方面就不得不考慮使用小型機了。在 2004 年的夏天,DBA 七公、測試工程師郭芙和架構師行癲,踏上了去北京測試小型機的道路。他們帶着小型機回來的時候,我們像歡迎領袖一樣的歡迎他們,因为那個是我們最值錢的設備了,價格表上的數字嚇死人。小型機買回來之後我們爭相合影,然後 Oracle 就跑在了小型機上,存儲方面從 EMC 低端 cx 存儲到 Sun oem hds 高端存儲,再到 EMC dmx 高端存儲,一級一級的往上跳。

到現在为止,我們已經用上了 IBM 的小型機、Oracle 的資料庫、EMC 的存儲,這些東西都是很貴的,那些年可以說是花錢如流水啊。有人說過“錢能解决的問題,就不是問題”,但隨着淘寶網的發展,在不久以後,錢已經解决不了我們的問題了。花錢買豪華的配置,也許能支持 1 億 PV 的網站,但淘寶網的發展實在是太快了,到了 10 億怎麼辦?到了百億怎麼辦?在 N 年以後,我們不得不創造技術,解决這些只有世界頂尖的網站才會遇到的問題。後來我們在開源軟件的基礎上進行自主研發,一步一步的把 IOE(IBM 小型機、Oracle、EMC 存儲)這幾個“神器”都去掉了。這就如同在《西遊記》裏面,妖怪們拿到神仙的兵器會非常厲害,連猴子都能夠打敗,但最牛的神仙是不用這些神器的,他們揮一揮衣袖、翻一下手掌就威力無比。去 IOE 這一部分會在最後一個章節裏面講,這裏先埋個千裏伏筆。

欲知後事如何,且聽下回分解。

五、淘寶技術發展(Java時代:堅若磐石)

已經有讀者在迫不及待的問怎麼去掉了 IOE,別急,在去掉 IOE 之前還有很長的路要走。行癲他們買回來小型機之後,我們用上了 Oracle,七公帶着一幫 DBA 在優化 SQL 和存儲,行癲帶着幾個架構師在研究資料庫的擴展性。Oracle 本身是一個封閉的系統,用 Oracle 怎麼做擴展?用現在一個時髦的說法就是做“分庫分表”。

我們知道一台 Oracle 的處理能力是有上限的,它的連接池有數量限制,查詢速度跟容量成反比。簡單的說,在資料量上億、查詢量上億的時候,就到它的極限了。要突破這種極限,最簡單的方式就是多用幾個 Oracle 資料庫。但一個封閉的系統做擴展,不像分散式系統那樣輕松。我們把用戶的信息按照 ID 來放到兩個資料庫裏面(DB1/DB2),把商品的信息跟着賣家放在兩個對應的資料庫裏面,把商品類目等通用信息放在第三個庫裏面(DBcommon)。這麼做的目的除了增加了資料庫的容量之外,還有一個就是做容災,萬一一個資料庫掛了,整個網站上還有一半的資料能操作。

資料庫這麼分了之後,應用程序有麻煩了,如果我是一個買家,買的商品有 DB1 的也有 DB2 的,要查看“我已買到的寶貝”的時候,應用程序怎麼辦?必須到兩個資料庫裏面分別查詢出來對應的商品。要按時間排序怎麼辦?兩個庫裏面“我已買到的寶貝”全部查出來在應用程序裏面做合並。還有分頁怎麼處理?關鍵字查詢怎麼處理?這些東西交给程序員來做的話會很悲催,於是行癲在淘寶的第一個架構上的作品就來解决了這個問題,他寫了一個資料庫路由的框架 DBRoute,這個框架在淘寶的 Oracle 時代一直在使用。後來隨着業務的發展,這種分庫的第二個目的 —— 容災的效果就沒有達到。像評價、投訴、舉報、收藏、我的淘寶等很多地方,都必須同時連接 DB1 和 DB2,哪個庫掛了都會導致整個網站掛掉。

上一篇說過,采用 EJB 其實是和 Sun 的工程師妥協的結果,在他們走了之後,EJB 也逐漸被冷落了下來。在 2005、2006年的時候,Spring 大放異彩,正好利用 Spring 的反射(IoC)模式替代了 EJB 的工廠模式,给整個系統精簡了很多代碼。

上一篇還說過,为了減少資料庫的壓力,提高搜索的效率,我們引入了搜索引擎。隨着資料量的繼續增長,到了 2005 年,商品數有 1663 萬,PV 有 8931 萬,注冊會員有 1390 萬,這给資料和存儲帶來的壓力依然山大,資料量大,性能就慢。親,還有什麼辦法能提升系統的性能?一定還有招數可以用,這就是緩存和 CDN(內容分發網络)。

你可以想象,九千萬的訪問量,有多少是在商品詳情頁面?訪問這個頁面的時候,資料全都是只讀的(全部從資料庫裏面讀出來,不寫入資料庫),如果把這些讀操作從資料庫裏面移到內存裏,資料庫將會多麼的感激涕零。在那個時候我們的架構師多隆大神,找到了一個基於 Berkeley DB 的開源的緩存系統,把很多不太變動的只讀信息放了進去。其實最初這個緩存系統還比較弱,我們並沒有把整個商品詳情都放在裏面,一開始把賣家的信息放裏面,然後把商品屬性放裏面,商品詳情這個字段太大,放進去受不了。說到商品詳情,這個字段比較恐怖,有人統計過,淘寶商品詳情打印出來平均有 5 米長,在系統裏面其實放在哪裏都不招人待見。筆者清楚的記得,我來淘寶之後擔任項目經理做的第一個項目就是把商品詳情從商品表裏面给移出來。這個字段太大了,查詢商品信息的時候很多都不需要查看詳情,它跟商品的價格、運費這些放在一個表裏面,拖慢了整個表的查詢速度。在 2005 年的時候,我把商品詳情放在資料庫的另外一張表裏面,再往後這個大字段被從資料庫裏面請了出來,這也讓資料庫再一次感激涕零。

到現在为止,整個商品詳情的頁面都在緩存裏面了,眼尖的讀者可能會發現現在的商品詳情不全是“只讀”的信息了,這個頁面上有個信息叫“瀏覽量”,這個數字每刷新一次頁面就要“寫入”資料庫一次,這種高頻度實時更新的資料能用緩存嗎?如果不用緩存,一天幾十億的寫入,資料庫會怎麼樣?一定會掛掉。那怎麼辦?親……先不回答你(下圖不是廣告,讓你看看瀏覽量這個資料在哪裏)

商品圖片

CDN 這個工作相對比較獨立,跟別的系統一樣,一開始我們也是采用的商用系統。後來隨着流量的增加,商用的系統已經撐不住了,LVS 的創始人章文嵩博士帶人搭建了淘寶自己的 CDN 網络。在本文的引言中我說過淘寶的 CDN 系統支撐了 800Gbps 以上的流量,作为對比我們可以看一下國內專業做 CDN 的上市公司 ChinaCache 的介紹 —— “ChinaCache……是中國第一的專業 CDN 服務提供商,向客戶提供全方位網络內容快速分布解决方案。作为首家獲信產部許可的 CDN 服務提供商,目前 ChinaCache 在全國 50 多個大中城市擁有近 300 個節點,全網處理能力超過 500Gbps,其 CDN 網络覆蓋中國電信、中國網通、中國移動、中國聯通、中國鐵通和中國教育科研網等各大運營商。” —— 這樣你可以看得出淘寶在 CDN 上面的實力,這在全世界都是數一數二的。另外因为 CDN 需要大量的服務器,要消耗很多能源(消耗多少?在前兩年我們算過一筆帳,淘寶上產生一個交易,消耗的電足以煮熟 4 個雞蛋)。這兩年章文嵩的團隊又在研究低功耗的服務器,在綠色計算領域也做了很多開創性的工作。淘寶 CDN 的發展需要專門一個章節來講,想先睹为快的可以看一下筆者對章文嵩的專訪

回想起剛用緩存那段時間,筆者還是個小菜鳥,有一個經典的錯誤常常犯,就是資料庫的內容更新的時候,忘記通知緩存系統,結果在測試的時候就發現我改過的資料怎麼在頁面上沒變化呢。後來做了一些頁面上的代碼,修改 CSS 和 JS 的時候,用戶本地緩存的信息沒有更新,頁面上也會亂掉,在論壇上被人說的時候,我告訴他用 Ctrl+F5 刷新頁面,然後趕緊修改腳本文件的名稱,重新發布頁面。學會用 Ctrl+F5 的會員對我佩服的五體投地,我卻慚愧的無地自容。

有些技術的發展是順其自然的,有些卻是突如其來的。到 2007 年的時候,我們已經有幾百台應用服務器了,這上面的 Java 應用服務器是 WebLogic,而 WebLogic 是非常貴的,比這些服務器本身都貴。有一段時間多隆研究了一下 JBoss,說我們換掉 WebLogic 吧,於是又省下了不少銀兩。那一年,老馬舉辦了第一屆的“網俠大會”,會上來的大俠中有一位是上文提到的章文嵩,還有一位曾經在 JBoss 團隊工作,我們也把這位大俠留下了,這樣我們用起 JBoss 更加有底氣了。

這些雜七雜八的修改,我們對資料分庫、放棄 EJB、引入 Spring、加入緩存、加入 CDN、採用開源的 JBoss,看起來沒有章法可循,其實都是圍繞着提高容量、提高性能、節約成本來做的,由於這些不算大的版本變遷,我們姑且叫它 2.1 版吧,這個版本從構圖上來看有 3 只腳,是不是穩定了很多?

架構圖如下:

架構圖

六、淘寶技術發展(Java時代:創造技術-TFS)

在講淘寶文件系統 TFS 之前,先回顧一下上面幾個版本。1.0 版的 PHP 系統運行了將近一年的時間(2003.05~2004.01);後來資料庫變成 Oracle 之後(2004.01~2004.05,叫 1.1 版本吧),不到半年就把開發語言轉換为 Java 系統了(2004.02~2005.03,叫2.0版本);進行分庫、加入緩存、CDN之後我們叫它 2.1 版本(2004.10~2007.01)。這中間有些時間的重合,因为很多架構的演化並沒有明顯的時間點,它是逐步進化而來的。

在描述 2.1 版本的時候我寫的副標題是“堅若磐石”,這個“堅若磐石”是因为這個版本終於穩定下來了,在這個版本的系統上,淘寶網運行了兩年多的時間。這期間有很多優秀的人才加入,也開發了很多優秀的產品,例如支付寶認證系統、招財進 寶項目、淘寶旅行、淘寶彩票、淘寶論壇等等。甚至在團購網站風起雲涌之前,淘寶網在 2006 年就推出了團購的功能,只是淘寶網最初的團購功能是買家發起的,達到賣家指定的數量之後,享受比一口價更低的價格,這個功能看起來是結合了淘寶一口價和荷蘭拍的另一種交易模式,但不幸沒有支撐下去。

在這些產品和功能的最底層,其實還是商品的管理和交易的管理這兩大功能。這兩大功能在 2.1 版本裏面都有很大的變化。商品的管理起初是要求賣家選擇 7 天到期還是 14 天到期,到期之後就要下架,必須重新發布才能上架,上架之後就變成了新的商品信息(ID變過了)。另外如果這個期間內成交了,之後再有新貨,必須發布一個新的商品信息。這麼做有幾個原因,一是参照拍賣商品的時間設置,要在某日期前結束掛牌;二是搜索引擎不知道同樣的商品哪個排前面,那就把掛牌時間長的排前面,這樣就必須在某個時間把老的商品下架掉,不然它老排在前面;第三是成交信息和商品 ID 關聯,這個商品如果多次編輯還是同一個 ID 的話,成交記錄裏面的商品信息會變來變去;還有一個不为人知的原因,我們的存儲有限,不能讓所有的商品老存放在主庫裏面。這種處理方式簡單粗暴,但還算是公平。不過這樣很多需求都無法滿足,例如同樣的商品,我上一次銷售的時候很多好評都沒法在下一個商品上體現出來;再例如我買過的商品結束後只看到交易的信息,不知道賣家還有沒有再賣了。後來基於這些需求,我們在 2006 年下半年把商品和交易拆開。一個商家的一種商品有個唯一的 ID,上下架都是同一個商品。那麼如果賣家改價格、庫存什麼的話,已成交的信息怎麼處理?那就在買家每交易一次的時候,都記錄下商品的快照信息,有多少次交易就有多少個快照。這樣買賣雙方比較爽了,给系統帶來了什麼?存儲的成本大幅度上升了!

存儲的成本高到什麼程度呢?資料庫方面提到過用了 IOE,一套下來就是千萬級別的,那幾套下來就是⋯⋯。另外淘寶網還有很多文件需要存儲,我們有哪些文件呢?最主要的就是圖片、商品描述、交易快照,一個商品要包含幾張圖片和一長串的描述信息,而每一張圖片都要生成幾張規格不同的縮略圖。在 2010 年,淘寶網的後端系統上保存着 286 億個圖片文件。圖片在交易系統中非常重要,俗話說“一張好圖勝千言”、“無圖無真相”,淘寶網的商品照片,尤其是熱門商品,圖片的訪問流量是非常大的。淘寶網整體流量中,圖片的訪問流量要占到 90% 以上。且這些圖片平均大小为 17.45 KB,小於 8K 的圖片占整體圖片數量 61%,占整體系統容量的 11%。這麼多的圖片資料、這麼大的訪問流量,给淘寶網的系統帶來了巨大的挑戰。眾所周知,對於大多數系統來說,最頭疼的就是大規模的小文件存儲與讀取,因为磁頭需要頻繁的尋道和換道,因此在讀取上容易帶來較長的延時。在大量高並發訪問量的情況下,簡直就是系統的噩夢。我們該怎麼辦?

同樣的套路,在某個規模以下,采用現有的商業解决方案,達到某種規模之後,商業的解决方案無法滿足,只有自己創造解决方案了。對於淘寶的圖片存儲來說,轉折點在 2007 年。這之前,一直采用的商用存儲系統,應用 NetApp 公司的文件存儲系統。隨着淘寶網的圖片文件數量以每年 2 倍(即原來 3 倍)的速度增長,淘寶網後端 NetApp 公司的存儲系統也從低端到高端不斷遷移,直至 2006 年,即使是 NetApp 公司最高端的產品也不能滿足淘寶網存儲的要求。從 2006 年開始,淘寶網决定自己開發一套針對海量小文件存儲的文件系統,用於解决自身圖片存儲的難題。這標志着淘寶網從使用技術到了創造技術的階段。

2007年之前的圖片存儲架構如下圖:

圖片儲存架構圖

章文嵩博士總結了幾點商用存儲系統的局限和不足:

首先是商用的存儲系統沒有對小文件存儲和讀取的環境進行有針對性的優化;其次,文件數量大,網络存儲設備無法支撐;另外,整個系統所連接的服務器也越來越多,網络連接數已經到達了網络存儲設備的極限。此外,商用存儲系統擴容成本高,10T的存儲容量需要幾百萬,而且存在單點故障,容災和安全性無法得到很好的保證。

談到在商用系統和自主研發之間的經濟效益對比,章文嵩博士列舉了以下幾點經驗:

1. 商用軟件很難滿足大規模系統的應用需求,無論存儲還是 CDN 還是負載均衡,因为在廠商實驗室端,很難實現如此大的資料規模測試。

2. 研發過程中,將開源和自主開發相結合,會有更好的可控性,系統出問題了,完全可以從底層解决問題,系統擴展性也更高。

投入 vs 規模

3. 在一定規模效應基礎上,研發的投入都是值得的。上圖是一個自主研發和購買商用系統的投入產出比對比,實際上,在上圖的交叉點左邊,購買商用系統都是更加實際和經濟性更好的選擇,只有在規模超過交叉點的情況下,自主研發才能收到較好的經濟效果。實際上,規模化達到如此程度的公司其實並不多,不過淘寶網已經遠遠超過了交叉點。

4. 自主研發的系統可在軟件和硬件多個層次不斷的優化。

曆史總是驚人的巧合,在我們准備研發文件存儲系統的時候,Google 走在了前面,2007 年他們公布了 GFS( Google File System )的設計論文,這给我們帶來了很多借鑒的思路。隨後我們開發出了適合淘寶使用的圖片存儲系統TFS(Taobao File System)。3年之後,我們發現曆史的巧合比我們想象中還要神奇,幾乎跟我們同時,中國的另外一家互聯網公司也開發了他們的文件存儲系統,甚至取的名字都一樣 —— TFS,太神奇了!(猜猜是哪家?)

2007 年 6 月,TFS 正式上線運營。在生產環境中應用的集群規模達到了 200 台 PC Server(146G*6 SAS 15K Raid5),文件數量達到上億級別;系統部署存儲容量:140TB;實際使用存儲容量: 50TB;單台支持隨機IOPS200+,流量 3MBps。

要講 TFS 的系統架構,首先要描述清楚業務需求,淘寶對圖片存儲的需求大概可以描述如下:

文件比較小;並發量高;讀操作遠大於寫操作;訪問隨機;沒有文件修改的操作;要求存儲成本低;能容災能備份。應對這種需求,顯然要用分散式存儲系統;由於文件大小比較統一,可以采用專有文件系統;並發量高,讀寫隨機性強,需要更少的 IO 操作;考慮到成本和備份,需要用廉價的存儲設備;考慮到容災,需要能平滑擴容。

参照 GFS 並做了適度的優化之後,TFS 1.0 版的架構圖如下:

TFS 1.0 架構圖

從上面架構圖上看:集群由一對 Name Server 和多台 Data Serve r構成,Name Server 的兩台服務器互为雙機,就是集群文件系統中管理節點的概念。

在這個架構中:

  • 每個 Data Server 運行在一台普通的 Linux 主機上
  • 以 block 文件的形式存放資料文件(一般64M一個block )
  • block 存多份保證資料安全
  • 利用 ext3 文件系統存放資料文件
  • 磁盤 raid5 做資料冗餘
  • 文件名內置元資料信息,用戶自己保存 TFS 文件名與實際文件的對照關系 – 使得原資料量特別小。

淘寶 TFS 文件系統在核心設計上最大的取巧的地方就在,傳統的集群系統裡面原資料只有 1 份,通常由管理節點來管理,因而很容易成为瓶頸。而對於淘寶網的用戶來說,圖片文件究竟用什麼名字來保存實際上用戶並不關心,因此TFS 在設計規劃上考慮在圖片的保存文件名上暗藏了一些原資料信息,例如圖片的大小、時間、訪問頻次等等信息,包括所在的邏輯塊號。而在原資料上,實際上保存的信息很少,因此原資料結構非常簡單。僅僅只需要一個 fileID,能夠准確定位文件在什麼地方。

由於大量的文件信息都隱藏在文件名中,整個系統完全拋棄了傳統的目錄樹結構,因为目錄樹開銷最大。拿掉後,整個集群的高可擴展性極大提高。實際上,這一設計理念和目前業界的“對象存儲”較为類似,淘寶網 TFS 文件系統已經更新到 1.3 版本,在生產系統的性能已經得到驗證,且不斷得到了完善和優化,淘寶網目前在對象存儲領域的研究已經走在前列。

在 TFS 上線之前,淘寶網每個商品只允許上傳一張圖片,大小限定在 120K 之內,在商品詳情裏面的圖片必須使用外站的服務。那時侯發布一件商品確實非常麻煩,筆者曾經想賣一台二手電腦,先把照片上傳到 Google 相冊,在發布到淘寶網之後發現 Google 相冊被牆了,我的圖片別人看不到,當時鬱悶的不行。TFS 上線後,商品展示圖片開放到 5 張,商品描述裏面的圖片也可以使用淘寶的圖片服務,到現在为止,淘寶網给每個用戶提供了 1G 的圖片空間,這下大家都滿足了。技術和業務就是這麼互相用力的推動着,業務滿足不了的時候,技術必須創新,技術創新之後,業務有了更大的發展空間。

1.3 版本的架構見阿里味(阿里巴巴內網)⋯⋯

七、淘寶技術發展(分散式時代:服務化)

在系統發展的過程中,架構師的眼光至關重要,作为程序員,把功能實現即可,但作为架構師,要考慮系統的擴展性、重用性,這種敏銳的感覺,有人說是一種代碼潔癖。淘寶早期有幾個架構師具備了這種感覺。一指開發的 Webx 是一個擴展性很強的框架,行癲在這個框架上插入了資料分庫路由的模塊、session 框架等等。在做淘寶後台系統的時候,同樣需要這幾個模塊,行癲指導我把這些模塊單獨打成了 jar 包。另外在做淘寶機票、彩票系統的時候,頁面端也有很多東西需要复用,最直觀的是頁頭和頁腳,一開始我們每個系統裡面複製了一份過去,但奇妙的是,那段時間頁腳要經常修改,例如把“雅虎中國”改成“中國雅虎”,過一段時間又加了一個“口碑網”,再過一段時間變成了“雅虎口碑”,最後又變成了“中國雅虎”,每個系統都改一遍,折騰啊。後來我就把這部分 velocity 模版單獨拿出來了,做成了公用的模塊。

上面這些都是比較小的复用模塊,到 2006 年我們做了一個商品類目屬性的改造,在類目裏面引入屬性的概念。項目的代號叫做“泰山”,如同它的名字,這是一個舉足輕重的項目,這個改變是一個劃時代的創新。在這之前的三年時間內,商品的分類都是按照樹狀的一級一級的節點來分的,隨着商品數量的增長,類目也變得越來越深,越來越复雜,這帶给買家的就是查找一件商品要逐級類目點開,找商品之前要懂商品的分類。而淘寶運營部門管理類目的小二也發現一個很嚴重的問題 —— 例如男裝裏面有T恤、T恤下面有耐克、耐克有純棉的,女裝裏面也有T恤、T恤下面還是有耐克、耐克下面依然有純棉的,那是先分男女裝再分款式再分品牌再分材質呢?還是先分品牌再分款式再分材質再分男女呢?暈倒了。這時候,一位大俠出來了 —— 一燈,他說品牌、款式、材質這種東東可以叫做“屬性”,屬性是類似 tag 的一個概念,與類目相比更加離散,更加靈活,這樣也縮減了類目的深度。這個思想的提出,一舉解决了分類的難題!從系統的角度來看,我們建立了“屬性”這樣一個資料結構,由於除了類目的子節點有屬性,父節點也有可能有屬性,於是類目屬性合起來也是一個結構化的資料對象。這個做出來之後我們把它獨立出來作为一個服務,叫做 catserver(category server)。跟類目屬性密切關聯的商品搜索功能,獨立出來,叫做 hesper(金星),catserver 和 hesper 供淘寶的前後台系統調用。

現在淘寶的商品類目屬性已經是地球上最大的了,幾乎沒有什麼類目的商品在淘寶上找不到(除了違禁的),但最初類目屬性改造完之後,我們很缺屬性資料,尤其是數碼類的最缺。那從哪裏弄這些資料呢親?我們跟“中關村在線”合作,拿到了很多資料,那個時候,很多商品屬性信息的後邊標注着:“來自中關村在線”。有了類目屬性,给運營的工作帶來很大的便利,我們知道淘寶的運營主要就是類目的運營,什麼季節推什麼商品,都要在類目屬性上面做調整,讓買家更容易找到。例如夏天我要用戶在女裝一級類目下就標出來材質是不是蕾絲的、是不是純棉的,冬天卻要把羽絨衣調到女裝一級類目下,流行什麼就要把什麼商品往更高級的類目調整。這樣類目和屬性要經常調整,隨之而來的問題就顯現了 —— 調整到哪個類目,那類商品的賣家就要編輯一次自己的商品,隨着商品量的增長,賣家的工作量越來越大,然後我們就發現賣家受不了啦。到了 2008 年,我們研究了超市裏面前後台商品的分類,發現超市前台商品可以隨季節和關聯來調整擺放場景(例如著名的啤酒和尿布的關聯),後台倉庫裏面要按照自然類目來存儲,二者密切關聯卻又相互分開。然後我們就把前後台類目分開了,這樣賣家發布商品選擇的是自然類目和屬性,淘寶前台展示的是根據運營需要而擺放的商品的類目和屬性。改造後的類目屬性服務取名叫做 forest(森林,跟類目屬性有點神似。catserver 還在,提供賣家授權、品牌服務、關鍵詞等相關的服務)。類目屬性的服務化,是淘寶在系統服務化方面做的第一個探索。

雖然個別架構師具備了代碼潔癖,但淘寶前台系統的業務量和代碼量還是爆炸式的增長了起來。業務方總在後面催,開發人員不夠了就繼續招人,招來的人根本看不懂原來的業務,只好摸索着在“合適的地方”加一些“合適的代碼”,看看運行起來像那麼回事,就發布上線了。在這樣的惡性循環中,系統越來越臃腫,業務的耦合性越來越高,開發的效率越來越低。借用當時比較流行的一句話“寫一段代碼,編譯一下能通過,半個小時就過去了;編譯一下沒通過,半天就過去了。”在這種情況下,系統出錯的概率也逐步增長,常常是你改了商品相關的某些代碼,發現交易出問題了,甚至你改了論壇上的某些代碼,旺旺出問題了。這讓開發人員苦不堪言,而業務方還認为這幫人幹活越來越慢了。

大概是在 2007 年底的時候,研發部空降了一位從矽穀來的高管,空聞大師。空聞是一位溫厚的長者,他告訴我們一切要以穩定为中心,所有影響系統穩定的因素都要解决掉。例如每做一個日常修改,都必須整個系統回歸測試一遍;多個日常修改如果放在一個版本裏面,要是一個功能沒有測試通過,整個系統都不能發布。我們把這個叫做“火車模型”,任何一個乘客沒有上車,都不許發車。這樣做的最直接後果就是火車一直晚點,新功能上線更慢了,我們能明顯的感覺到業務方的不滿,空聞的壓力肯定非常大。當時我都不理解這種一刀切的做法,为了穩定犧牲了發展的速度,這跟某 Party 的“穩定壓倒一切”有什麼分別?

但是到現在回過頭來看看,其實我們並沒有理解背後的思路。正是在這種要求下,我們不得不開始改變一些東西,例如把回歸測試日常化,每天晚上都跑一遍整個系統的回歸。還有就是在這種要求下,我們不得不對這個超級复雜的系統做肢解和重構,其中复用性最高的一個模塊 —— 用戶信息模塊開始拆分出來了,我們叫它 UIC(user information center)。在 UIC 裏面,它只處理最基礎的用戶信息操作,例如getUserById、getUserByName等等。

在另外一個方面,還有兩個新興的業務,也對系統基礎功能的拆分提出了要求。在那個時候,我們做了淘寶旅行(trip.taobao.com)和淘寶彩票(caipiao.taobao.com)兩個新業務,這兩個新業務在商品的展示和交易的流程上都跟主站的業務不一樣,機票是按照航班的信息展示的,彩票是按照雙色球、數字和足球的賽程來展示的。但用到的會員的功能和交易的功能是跟主站差不多的,當時做的時候就很糾結,在主站裏面做的話,會有一大半跟主站無關的東西,重新做一個的話,會有很多重复建設。最終我們决定不再给主站添亂了,就另起爐灶做了兩個新的業務系統。從查詢商品、購買商品、評價反饋、查看訂單這一整個流程都重新寫了一套出來。現在在“我的淘寶”裏面查看交易記錄的時候,還能發現“已買到的寶貝”裏面把機票和彩票另外列出來了,他們沒有加入到普通的訂單裏面去。在當時如果已經把會員、交易、商品、評價這些模塊拆分出來,就不用什麼都重做一遍了。

到2008年初,整個主站系統(有了機票、彩票系統之後,把原來的系統叫做主站)的容量已經到了瓶頸,商品數在一億以上,PV在2.5億以上,會員數超過了五千萬。這個時候Oracle 的連接池數量都不夠用了,資料庫的容量到了極限,上層系統再增加機器也無法繼續擴容了,我們只有把底層的基礎服務繼續拆分,從底層開始擴容,上層才能擴展,這才能容納以後三五年的增長。

於是那一年我們專門啟動了一個更大的項目,把交易這個核心業務模塊也拆分出來了。原來的淘寶交易除了跟商品管理耦合在一起,也在支付寶和淘寶之間跳來跳去,跟支付寶耦合在一起,系統復雜,用戶體驗也很不好。我們把交易的底層業務拆出來叫交易中心TC(trade
center),所謂底層業務是例如創建訂單、減庫存、修改訂單狀態等原子型的操作;交易的上層業務叫交易管理TM(trade manager),例如拍下一件普通商品要對訂單、庫存、物流進行操作,拍下虛擬商品不需要對物流進行操作,這些在TM裡面完成。這個項目取了一個很沒有創意的名字——“千島湖”,這幫開發人員取這個名字的目的是想在開發完畢之後,去千島湖玩一圈,後來他們如願以償了。這個時候還有一個項目也在搞,就是淘寶商城,之前拆分出來的那些基礎服務,給商城的快速構建,提供了良好的基礎。

類目屬性、用戶中心、交易中心,隨著這些模塊逐步的拆分和服務化改造,我們在系統架構方面也積累了不少的經驗。到2008年底乾脆做了一個更大的項目,把淘寶所有的業務都模塊化,這是繼2004年從LAMP架構到Java架構之後的第二次脫胎換骨。這個項目取了一個很霸氣的名字,叫“五彩石”(女媧煉石補天,用的石頭)。這個系統重構的工作非常驚險,有人稱之為“給一架高速飛行的飛機換發動機”。

五彩石項目發布之後,這幫工程師去三亞玩了幾天。他們把淘寶的系統拆分成瞭如下架構:

系統架構

其中 UIC 和 Forest 上文說過,TC、IC、SC分別是交易中心(Trade Center)、商品中心(Item Center)、店鋪中心(Shop Center),這些中心級別的服務只提供原子級的業務邏輯,如根據ID查找商品、創建交易、減少庫存等操作。再往上一層是業務系統TM(Trade Manager交易業務)、IM(Item Manager商品業務)、SM(Shop Manager,因为不好聽,所以後來改名叫 SS:Shop System,店鋪業務)、Detail(商品詳情)。

拆分之後,系統之間的交互關系變得非常复雜,示意圖如下:

系統交互關係圖

系統這麼拆分的話,好處顯而易見,拆分之後每個系統可以單獨部署,業務簡單,方便擴容;有大量可重用的模塊以便於開發新的業務;能夠做到專人專事,讓技術人員更加專注於某一個領域。這樣要解决的問題也很明顯,分拆之後,系統之間還是必須要打交道的,越往底層的系統,調用它的客戶方越多,這就要求底層的系統必須具有超大規模的容量和非常高的可用性。另外,拆分之後的系統如何通訊?這裏需要兩種中間件系統,一種是實時調用的中間件(淘寶的HSF,高性能服務框架)、一種是異步消息通知的中間件(淘寶 Notify)。

另外還有一個需要解决的問題是用戶在A系統登錄了,到B系統的時候,用戶的登錄信息怎麼保存?這又涉及到一個 Session 框架。再者,還有一個軟件工程方面的問題,這麼多層的一套系統,怎麼去測試它?

作者: Tsung

對新奇的事物都很有興趣, 喜歡簡單的東西, 過簡單的生活.

在〈淘寶的起源故事、技術發展之路 - 2013〉中有 1 則留言

發表迴響

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料