當(dāng)一個開發(fā)人員提升計算機系統(tǒng)負荷時,通常會考慮兩種方式垂直擴展和水平擴展。選用哪種策略主要依賴于要解決的問題以及系統(tǒng)資源的限制。在這篇文章中我們將講述這兩種策略并討論每種策越的優(yōu)缺點。如果你已經(jīng)有一個軟件系統(tǒng)需要不斷成長,那么你將有意或者無意中選擇這兩種策略中的一種。
垂直擴展
在垂直擴展模型中,想要增加系統(tǒng)負荷就意味著要在系統(tǒng)現(xiàn)有的部件上下工夫,即通過提高系統(tǒng)部件的能力來實現(xiàn)。例如,假設(shè)你現(xiàn)在負責(zé)一批木材采伐的操作。
在這個例子中,我們假設(shè)有3輛卡車,每輛車一次可以運25根木材,計算花費1小時的情況下可以運送到指定地點等待處理的木材數(shù)量。通過這些數(shù)字我們可以算出我們系統(tǒng)最大的負荷量:
3輛卡車 * 25根木材 * 1小時=75根木材/小時
如果我們選擇垂直擴展模型,那么我們將怎么做來使我們每小時可以處理150根木材?我們需要至少做以下兩件事中的一件:
使每輛卡車的運輸量增加一倍(50棵樹每小時),或者使每輛卡車的運輸時間減半(每輛卡車30分鐘)。
3輛卡車 * 50棵樹 * 1小時 = 150棵樹/每小時
或者
3輛卡車 * 25棵樹 * 30分鐘 = 150棵樹/每小時
我們沒有增加系統(tǒng)的成員數(shù),但是我們通過增加系統(tǒng)成員的生產(chǎn)效率來獲得期望的負荷量。
水平擴展
在水平擴展模型中,我們不是通過增加單個系統(tǒng)成員的負荷而是簡單的通過增加更多的系統(tǒng)成員來實現(xiàn)。也就是說,在以上運送木材的例子中,通過增加卡車的數(shù)量來運送木材。因此,當(dāng)我們需要將負荷從75棵樹每小時增加到150棵樹每小時,那么只需要增加3輛卡車。
6輛卡車 * 25棵樹 * 1小時 = 150棵樹/每小時
假如我們已經(jīng)選擇了垂直擴展方式,那么我們想要每小時處理150棵被砍伐的樹時需要怎么做呢?我們需要做到以下兩方面之一:要么使每輛卡車的運輸量翻倍(50棵木材一次),要么使每輛開車的運輸時間減半(30分鐘)。
3輛卡車 * 50棵樹 * 1小時 = 150棵樹/每小時
或者
3輛卡車 * 50棵樹 * 30分鐘 = 150棵樹/每小時
在這個例子中,系統(tǒng)每個成員的生產(chǎn)力依然沒變,我們通過增加更多的卡車來提高系統(tǒng)的能力。
擴展你的web數(shù)據(jù)庫
通過對水平擴展和垂直擴展的基本了解,下面讓我們來關(guān)注web系統(tǒng)的擴展。一個網(wǎng)站通常有很多組件都需要去考慮它們的擴展性,但是我通常喜歡關(guān)注處在最邊緣的一個:數(shù)據(jù)庫。為什么數(shù)據(jù)庫是最邊緣的?因為數(shù)據(jù)庫通常是共享資源,是幾乎所有請求最終的連接點。
你的系統(tǒng)是什么類型的?
在擴展你的數(shù)據(jù)庫時,你必須要問的一個重要問題是:“我所面對的系統(tǒng)是什么類型的?”你所面對的是一個讀操作多還是寫操作多的系統(tǒng)?讀操作多的網(wǎng)站一般包括:在線商城,在商城里用戶大部時間是在瀏覽(讀操作),只有少數(shù)時間在付款(寫操作)、或者博客,在博客上人們大部分時間是在瀏覽博文(讀操作),只有少數(shù)時間是在評論或者發(fā)表博文(寫操作)。相反的,關(guān)于寫操作非常多的很好的例子包括:信用卡交易處理器,這個系統(tǒng)的主要負載時在處理記錄交易(寫操作),偶爾會查找交易(讀操作)、或者Google分析,主要工作實在記錄業(yè)務(wù)數(shù)據(jù)(寫操作),偶爾會展示分析圖(讀操作)。
了解你所創(chuàng)建的網(wǎng)站是什么類型的,可以在網(wǎng)站成長過程中幫助你選擇正確的技術(shù)。
讀操作擴展
如果你的系統(tǒng)讀操作非常多,那么通過關(guān)系型數(shù)據(jù)庫如MySQL或者PostgreSql來垂直擴展數(shù)據(jù)存儲是一個不錯的選擇。結(jié)合你的關(guān)系型數(shù)據(jù)庫通過使用memcached或者CDN來構(gòu)建一個健壯的緩存系統(tǒng),那么你的系統(tǒng)將非常容易擴展。在這種模式中,如果數(shù)據(jù)庫超負荷運行,那么將更多的數(shù)據(jù)放入緩存中來緩解系統(tǒng)的讀壓力。當(dāng)沒有更多的數(shù)據(jù)往緩存中放時,可以更換更快的數(shù)據(jù)存儲硬件或者買更多核的處理器來獲取更多的運行通道。摩爾定律使通過這種方法來垂直擴展變得和購買更好的硬件一樣簡單。
寫操作擴展
如果你的系統(tǒng)寫操作非常多,那么你可能更希望考慮使用可水平擴展的數(shù)據(jù)存儲方式,比如Riak,Cassandra或者HBase。和大多數(shù)關(guān)系型數(shù)據(jù)管理系統(tǒng)不同,這種數(shù)據(jù)存儲隨著增長增加更多的節(jié)點。由于你的系統(tǒng)大部分時間是在寫入,所以緩存曾并不能像在讀操作比較頻繁的系統(tǒng)中起到那么大作用。很多寫頻繁的系統(tǒng)一開始使用垂直擴展的方式,但是很快發(fā)現(xiàn)并不能根本解決問題。為什么?因為硬盤數(shù)和處理器數(shù)在某一點達到平衡,在這個邊界上再增加一個處理器或者一個硬盤都會是每秒鐘的I/O操作數(shù)成指數(shù)性增長。相反,如果對寫頻繁的系統(tǒng)采取水平擴展策略,那么你將達到一個拐點,在這個拐點之后如果在增加一個節(jié)點都遠比使用更多的硬盤來的實惠。
其他注意事項
另一件事需要記住的是每種擴展策略下預(yù)想不到的開銷。采用垂直擴展的系統(tǒng)將開銷凡在單獨的組件上。當(dāng)我們?nèi)ヌ嵘到y(tǒng)負荷時,這些單獨的組件需要在管理上花費更多。拿我們運送木材的例子來說,如果需要使每輛卡車的貨運量翻倍,那么我們需要更寬、更長、或者更高的車廂。也許有的路因為橋的高度對車輛高度有要求,或者基于巷子寬度車寬不能太大,又或者由于機動車安全駕駛要求車廂不能太長。這里的限制就是對單個卡車做垂直擴展做的什么程度。同樣的概念延伸到服務(wù)器垂直擴展:更多的處理器要求更多的空間,進而要求更多的服務(wù)器存儲架。
相反的,采用水平擴展的系統(tǒng)將額外的開銷放在系統(tǒng)中連接起來的共享組件上。當(dāng)我們?nèi)ヌ嵘到y(tǒng)負荷時,共享的開銷和新增加的成員之間的協(xié)調(diào)性有關(guān)。在我們運送木材的例子中,當(dāng)我們在路上增加更多卡車時,那么路就是共享資源也就成了約束條件。這條路上適合同時跑多少量卡車?我們是否有足夠的安全緩沖區(qū)使得所有的車可以同時裝運木材?如果再來看我們水平擴展的數(shù)據(jù)庫系統(tǒng),那么經(jīng)常被忽略的開銷就是服務(wù)器同時連接時的網(wǎng)絡(luò)開銷(譯者注:網(wǎng)絡(luò)為各個系統(tǒng)的共享資源)。當(dāng)你為系統(tǒng)增加更多的節(jié)點時,共享資源的負荷也就越來越重,通常呈非線性改變。
綜合說明
和計算機的大多數(shù)東西一樣,好的解決辦法通常并不像我這里列出來的這么簡單。而我在這里嘗試簡化這種思想用來來說明這中概念而不是講具體的解決辦法。擴展是個困難的問題,這是個需要在實際處理的每個步驟中都要思考的問題。擴展策略沒有魔法,也沒有魔法般的軟件幫你建立一個完整可靠的可擴展系統(tǒng)。就像擴展中的其他問題一樣,一個大的解決方案通常是由很多個一起協(xié)調(diào)工作的小的解決辦法組成的。這需對每一個中解決方案進行精心正確的設(shè)計和開發(fā)。