大型網站架構演進
一般來講,大型網站都是從小型網站發展而來,一開始的架構都比較簡單,隨著業務複雜和使用者量的激增,才開始做很多架構上的改進。當它還是小型網站的時候,沒有太多訪客,一般來講只需要一臺伺服器就夠了,這時應用程式、資料庫、檔案等所有資源都在一臺伺服器上,網站架構如下圖所示:
<img src="https://pic2.zhimg.com/b1fb995ac418a4bb50bdb976d52a6c31_b.png" data-rawwidth="341" data-rawheight="239" class="content_image" width="341">2. 應用服務和資料服務分離
隨著網站業務的發展和使用者量的增加,一臺伺服器就無法再滿足需求了。大量使用者訪問導致訪問速度越來越慢,而逐漸增加的資料也會導致儲存空間不足。這時就需要將應用和資料分離,應用和資料分離後整個網站使用 3 臺伺服器:應用伺服器、檔案伺服器和資料庫伺服器。這 3 臺伺服器對硬體資源的要求各不相同:
- 應用伺服器業務邏輯,需要強大的CPU
- 資料庫伺服器對磁碟讀寫操作很多,需要更快的磁碟和更大的記憶體
- 檔案伺服器儲存使用者上傳的檔案,因此需要更大的磁碟空間
此時,網站系統的架構如下圖所示:
<img src="https://pic1.zhimg.com/f6d05e8fafd86940614503fdb53dd608_b.png" data-rawwidth="445" data-rawheight="317" class="origin_image zh-lightbox-thumb" width="445" data-original="https://pic1.zhimg.com/f6d05e8fafd86940614503fdb53dd608_r.png">3. 使用快取改善網站效能
隨著使用者再增加,網站又會一次面臨挑戰:資料庫壓力太大導致整站訪問效率再此下降,使用者體驗受到影響。一個網站,往往 80% 的業務訪問集中在 20% 的資料上,比如微博請求量最多的肯定是那些千萬級粉絲的大 V 的微博,而幾乎沒有人關注的你的首頁,除了自己想起來之外根本不會被開啟。既然大部分業務訪問集中在一小部分資料上,那就把這一小部分資料先提前快取在記憶體中,而不是每次都去資料庫讀取,這樣就可以減少資料庫的訪問壓力,從而提高整個網站的訪問速度。
網站使用的快取一般分為快取到應用伺服器或者快取在專門的分散式快取伺服器。快取到應用伺服器自己的訪問速度快很多,但是受自身記憶體限制,往往不太適用。遠端分散式快取使用一個叢集專門負責快取服務,當記憶體不夠還可以輕鬆得動態擴容。
4. 使用應用伺服器叢集改善網站的併發處理能力
使用快取後,資料訪問壓力得到了緩解,但是單一應用伺服器能夠處理的請求連線有限,在網站訪問高峰期,應用伺服器就成了整個網站的效率瓶頸。使用分散式叢集是網站解決高併發、海量資料問題的常用手段。當一臺伺服器的處理能力和儲存空間不足時,不要嘗試去更換更強大的伺服器,對大型網站而言,多麼強大的伺服器,都滿足不了網站持續增長的業務需求。這種情況下,更恰當的做法是增加一臺伺服器分擔原有伺服器的訪問及儲存壓力。 對網站架構而言,只要能通過增加一臺伺服器的方式改善負載壓力,就可以以同樣的方式持續增加伺服器不斷改善系統性能,從而實現系統的可伸縮性。應用伺服器實現叢集是網站可伸縮架構設計中較為簡單成熟的一種,如下圖所示:
<img src="https://pic3.zhimg.com/758b0d2283f0c8fe32059ef718aa9a1e_b.png" data-rawwidth="747" data-rawheight="459" class="origin_image zh-lightbox-thumb" width="747" data-original="https://pic3.zhimg.com/758b0d2283f0c8fe32059ef718aa9a1e_r.png">通過負載均衡排程伺服器,可以將來自使用者瀏覽器的訪問請求分發到應用伺服器叢集中的任何一臺伺服器上,如果有更多使用者,就在叢集中加入更多的應用伺服器,使應用伺服器的壓力不再成為整個網站的瓶頸。
5. 資料庫讀寫分離
網站在使用快取後,使對大部分資料讀操作訪問都可以不通過資料庫就能完成,但是仍有一部分讀操作(快取訪問不命中、快取過期)和全部的寫操作都需要訪問資料庫,在網站的使用者達到一定規模後,資料庫因為負載壓力過高而成為網站的瓶頸。 目前大部分的主流資料庫都提供主從熱備功能,通過配置兩臺資料庫主從關係,可以將一臺資料庫伺服器的資料更新同步到另一臺伺服器上。網站利用資料庫的這一功能,實現資料庫讀寫分離,從而改善資料庫負載壓力。如下圖所示:
應用伺服器在寫資料的時候,訪問主資料庫,主資料庫通過主從複製機制將資料更新同步到從資料庫,這樣當應用伺服器讀資料的時候,就可以通過從資料庫獲得資料。為了便於應用程式訪問讀寫分離後的資料庫,通常在應用伺服器端使用專門的資料訪問模組,使資料庫讀寫分離對應用透明。
<img src="https://pic4.zhimg.com/3611799b5b84326062b86f7e8383b5e3_b.png" data-rawwidth="747" data-rawheight="569" class="origin_image zh-lightbox-thumb" width="747" data-original="https://pic4.zhimg.com/3611799b5b84326062b86f7e8383b5e3_r.png">
6. 使用反向代理和 CDN 加速網站響應
隨著網站業務不斷髮展,使用者規模越來越大,由於中國複雜的網路環境,不同地區的使用者訪問網站時,速度差別也極大。有研究表明,網站訪問延遲和使用者流失率正相關,網站訪問越慢,使用者越容易失去耐心而離開。為了提供更好的使用者體驗,留住使用者,網站需要加速網站訪問速度。主要手段有使用 CDN 和反向代理。如下圖所示:
<img src="https://pic4.zhimg.com/cf613de59351dc6209fc23c722351adf_b.png" data-rawwidth="811" data-rawheight="572" class="origin_image zh-lightbox-thumb" width="811" data-original="https://pic4.zhimg.com/cf613de59351dc6209fc23c722351adf_r.png">7. 使用分散式檔案系統和分散式資料庫系統
任何強大的單一伺服器都滿足不了大型網站持續增長的業務需求。資料庫經過讀寫分離後,從一臺伺服器拆分成兩臺伺服器,但是隨著網站業務的發展依然不能滿足需求,這時需要使用分散式資料庫。檔案系統也一樣,需要使用分散式檔案系統。如下圖所示:
<img src="https://pic2.zhimg.com/b41911410fd25fe17e53b8d99ee2808d_b.png" data-rawwidth="808" data-rawheight="506" class="origin_image zh-lightbox-thumb" width="808" data-original="https://pic2.zhimg.com/b41911410fd25fe17e53b8d99ee2808d_r.png">分散式資料庫是網站資料庫拆分的最後手段,只有在單表資料規模非常龐大的時候才使用。不到不得已時,網站更常用的資料庫拆分手段是業務分庫,將不同業務的資料部署在不同的物理伺服器上。
8. 使用 NoSQL 和搜尋引擎
隨著網站業務越來越複雜,對資料儲存和檢索的需求也越來越複雜,網站需要採用一些非關係資料庫技術如 NoSQL 和非資料庫查詢技術如搜尋引擎。如下圖所示:
<img src="https://pic3.zhimg.com/25f90e03351f541671aea86a488ae322_b.png" data-rawwidth="808" data-rawheight="506" class="origin_image zh-lightbox-thumb" width="808" data-original="https://pic3.zhimg.com/25f90e03351f541671aea86a488ae322_r.png">NoSQL 和搜尋引擎都是源自網際網路的技術手段,對可伸縮的分散式特性具有更好的支援。應用伺服器則通過一個統一資料訪問模組訪問各種資料,減輕應用程式管理諸多資料來源的麻煩。
9. 業務拆分
大型網站為了應對日益複雜的業務場景,通過使用分而治之的手段將整個網站業務分成不同的產品線。如大型購物交易網站都會將首頁、商鋪、訂單、買家、賣家等拆分成不同的產品線,分歸不同的業務團隊負責。
具體到技術上,也會根據產品線劃分,將一個網站拆分成許多不同的應用,每個應用獨立部署。應用之間可以通過一個超連結建立關係(在首頁上的導航連結每個都指向不同的應用地址),也可以通過訊息佇列進行資料分發,當然最多的還是通過訪問同一個資料儲存系統來構成一個關聯的完整系統,如下圖所示:
<img src="https://pic2.zhimg.com/cc6bd78d9d214d5e0fe6283b5ac2a3e5_b.png" data-rawwidth="831" data-rawheight="506" class="origin_image zh-lightbox-thumb" width="831" data-original="https://pic2.zhimg.com/cc6bd78d9d214d5e0fe6283b5ac2a3e5_r.png">10. 分散式服務
隨著業務拆分越來越小,儲存系統越來越龐大,應用系統的整體複雜度呈指數級增加,部署維護越來越困難。由於所有應用要和所有資料庫系統連線,在數萬臺伺服器規模的網站中,這些連線的數目是伺服器規模的平方,導致資料庫連線資源不足,拒絕服務。
既然每一個應用系統都需要執行許多相同的業務操作,比如使用者管理、商品管理等,那麼可以將這些共用的業務提取出來,獨立部署。由這些可複用的業務連線資料庫,提供共用業務服務,而應用系統只需要管理使用者介面,通過分散式服務呼叫共用業務服務完成具體業務操作。如下圖所示:
<img src="https://pic1.zhimg.com/694fb3f64b999a481b9b1166e6c09600_b.png" data-rawwidth="974" data-rawheight="506" class="origin_image zh-lightbox-thumb" width="974" data-original="https://pic1.zhimg.com/694fb3f64b999a481b9b1166e6c09600_r.png">
大型網站的架構演化到這裡,基本上大多數的技術問題都可以得以解決了。