一至千萬的藝術 — 如何養成支撐網路巨量交易的伺服器艦隊
淘寶網近日創下天文數字的成交金額。除了震撼,許多人多少會好奇淘寶網如何完成海量資料的處理。筆者身為工程師,想從淺顯易懂的角度帶領讀者瞭解像這樣的電子商務網站,通常是如何從小規模,一步一步的演變至今天的驚人海量地步。
停機一天都受不了
可靠性是指一個服務運行期間出現錯誤的狀況。擴展性是指這一個網路服務,可以透過增加主機數量台提升整體的承載能力。
可得性是指服務保持在線上可以使用的狀態所佔的時間比例,一般常用幾個 9 來表示。例如一個網站在一個月裡有 1% 的時間發生當機的話,我們就稱它的可得性在這段期間是 99%。如果只有 0.1% 的時間離線,那它的可得性就是 99.9%。可得性每增加一個 9 的代價都十分昂貴,每多一個 9 的成本甚至是以指數的型式成長。知名程式開發協作平台 Github 的
狀態頁面上就顯示了它在特定時間內的可得性和可靠性。
一個團隊的技術功力可以從可得性和擴展性看出端倪。這牽涉到了伺服器艦隊(fleet)的架構設計;好的設計師能設計良好的系統架構,達成高度擴展性和可得性。
以下我們從簡入繁,想像一個電子商務網站從剛出生時,隨著流量成長,如何透過伺服器的架構設計逐步承載越來越多的使用量。
艦隊的第一艘船
一般網站在草創期間,使用量不大,基於成本考量往往會把網頁應用伺服器(Web Application Server)和資料庫伺服器(Database server)放置於同一台主機上,如下圖:
這種架構能勉強支撐十萬至數十萬等級的使用者。實際能承受的量依照機器硬體的等級而定。然而硬體的等級不管如何提升,終究有一定的上限。屆時,當承載量再次增加,問題就會顯露無遺。在專業術語上我們稱之為瓶頸(
Bottleneck)。
這就像當台北捷運所有線路都交會於台北車站一個點時,台北車站就是瓶頸。整個捷運系統的承載量會因為這一個單點而受到限制。就像下面的「模擬都市」遊戲截圖所示,一條馬路不管有多少線道。當其中有一個窄口,整條馬路的流量都會受限於窄口。
各司其職
當網頁伺服器和資料庫共用一台主機,等於在競爭同一台主機的資源。為了分散負荷,一般都會將網頁伺服器和資料庫獨立放到不同的主機上。
然而這只稍微爭取到了一點喘息的空間,當使用量一多,很快又會填滿單一台機器的承載限制
艦隊添購新船
隨著使用量的增加,是時候擴充鑑隊規模了。為了讓網頁應用伺服器能夠處理大量請求,因此會增設多台網頁應用伺服器。但這產生了一個問題,因為使用者只認得一個網址,為了讓連線到同一個網址的請求分配到不同主機上,還得在前面擺一個「負載平衡器」(
Load balancer)。
負載平衡器的運作原理就像大家平常去銀行或郵局,窗口一字排開。每個人進去先領一個號碼,當叫到自己號碼時就到對應窗口去,透過這種方式把用量平均散到所有的應用伺服器上。
當走到這一步,大約的承載能力大略可以突破百萬使用者。但從圖中相信讀者也可以看出,資料庫只有一台,因此成為了新的瓶頸。當這台伺服器來不及處理讀取或寫入資料的請求時,前端有再多的網頁應用伺服器也沒有用。
讀寫分離
為了減輕資料庫的負擔,接著要引入一個概念 –「讀寫分離」。資料庫面對的有讀取和寫入兩種請求。當網頁應用程式要顯示商品資訊,它就得向資料庫送出讀取請求;當有使用者購買商品時,才需要寫入。
電子商務網站的使用者逛的次數遠大於買的次數,也就是讀取數量遠大於寫入。針對這個特性,我們可以增設多台只供讀取不供寫入的次要資料庫,它們的資料都從主要的資料庫複製而來。當網頁應用伺服器遇到商品資訊讀取時就向次要資料庫請求,當遇到購物等需要寫入時才向主要伺服器請求。如此一來最大宗的讀取壓力被分散到多台的次要資料庫身上,解決了瓶頸的問題。
走到這一步,大略的承載能力可能落在數百萬的數量級。
資料庫碎片
事情似乎很美好。但不幸的是當購物量也不停增加時,主要的資料庫還是很快會成為瓶頸。除此之外,若主要資料庫一旦當機,也會造成購物無法進行,形成了失效單點。
為了解決此問題,在此時一般會引入資料庫的碎片(
Shrading)技術。簡單的來說,將大量的資料分成一小群一小群,分別塞到不同的資料庫主機裡,當要查詢或寫入時,再看這一筆資料落在哪一台機器裡。
當走到這一步,整體艦隊的承載能力已經可以達到千萬等級了。
然而資料庫碎片雖然可以分散承載量到不同的機器,卻也增加了應用程式的難度與複雜度。有些企業會用 NoSQL 而非用碎片來解決這類問題,例如
Cassandra、
HBase;也有人自行發展技術來處理這部份的問題。
冰山一角
講到這裡,這趟旅程其實離走完還有一段很長的路。
上述的過程雖然未必精準的描述了淘寶網或類似網站的架構成長,但相信至少在讀者心中建立一個網站一步步提升承載能力的概念與想像。當然這過程省略、簡化了許多細節,例如負載平衡器本身也是一個瓶頸,可以使用
DNS 負載平衡器來解決;或是細部上可透過 CDN(
Content Deliever Network)來分佈靜態資源檔,降低艦隊的壓力;伺服器出錯、甚至資料中心出狀況也還沒詳細考量進來;以及使用快取伺服器(Cache server)取代資料庫等手法。
上述所列的是主流解法,遇到不同類形的需求得想出不同的對應方法。有時改變商務流程也不失為解決方法之一。網站的成長並非只在承載量,服務的數量與複雜程度也會隨時間成長,要如何將不同的服務獨立出來也並不簡單。同時,當架構改變,如何將對使用者的衝擊過降至最小也是一門藝術。
當承載需求再提昇,除了使用現成的解決方案,可能還要自行研發一整套針對某個問題的解決方案,例如淘寶網就大方的
開源分享了其中一些專案。這些其實體現了現今兩岸網路軟體界技術能量的差距。對淘寶網的發展歷史有進一步興趣的讀者可以參考以下一系列文章:
或是這一篇
有趣的是,淘寶在增加負載量的過程中同時採用了硬體和商業的解決方案。後來雖然提升了承載能力一段時間,旦很快的發現這些昂貴的硬體和商用資料庫反而變成繼續擴展的瓶頸,因此最後轉向純軟體的開源解決方案,顯示了業界從商業用軟硬體的解決方案轉向純軟體解決方案的風向。
除此之外讀者也可以參考美國歐巴馬在 2012 年競選總統時,其背後規模宏大的
伺服器艦隊架構圖。
2008 歐巴馬選總統時的伺服器艦隊的一部分。圖片來源:
awsofa
紮穩馬步,再戰十年
身為一個技術人員我懂得不多,但是我看到了問題,並且有一點想法與心得。軟體的開發就像紮馬步,在全世界的所有產業都被軟體和網路所劇烈改變的當下,需要把基本功練好才能應戰。
因此我寫了一本書叫做「
台灣軟體產業的失落十年」,其中所指的軟體產業的範圍包括網路產業。失落十年的意涵是指落後國外十年的技術、觀念與各種不同的面向。這本書不只寫給技術人看,也希望對於管理者或決策者有一些幫助。過一陣子就會上架,歡迎有興趣的讀者
前往購買。