大型網站架構的技術演進
網站初期架構
幾乎所有的大型網站都是從小型網站發展而來的,網站架構也一樣,是從小型網站技術架構逐步演化而來的。小型網站最開始沒有太多訪問量,可能只需要一臺伺服器就能夠應付了,這時的網站架構如下圖所示。
即將應用程式、資料庫、檔案等所有的資源都在同一臺伺服器上。很多時候,是彙集免費開源軟體及廉價伺服器開始的,例如:Linux+PHP+Apache+Mysql.
應用服務與資料服務分離
隨著網站業務的發展,使用者多了,導致效能越來越差,越來越多的資料導致儲存空間不不足,一臺伺服器再也不能滿足需求了。於是將應用與資料進行分離,如下圖所示。
有過架構經驗的同學應該知道,這三臺伺服器對硬體資源的要求會各不相同,應用伺服器需要處理大量業務邏輯,因此需要更快更高頻的CPU;資料庫伺服器需要快速磁碟檢索和資料快取,因此需要更快的硬碟和更大的記憶體;檔案伺服器需要儲存大量使用者上傳的檔案,因此需要更大的硬碟。
使用快取改善網站效能
隨著使用者數量逐漸增多,只是簡單的將應用與資料分離的架構會出現資料庫壓力太大導致訪問延遲,從而影響整個網站的效能。一般企業都會對使用者的行為資料進行分析,這裡應該主要是從訪問量整個角度去解讀,即80%的業務訪問集中在20%的資料上。例如:淘寶買家瀏覽的商品集中在少部分銷量多、評價良好的商品上;百度搜索關鍵詞集中在少部分熱門詞彙上;只有經常登入的使用者才會發微博、看微博,這些使用者只佔總使用者數目的一小部分。
有了這個結論,解決辦法也就有了。既然大部分的業務訪問集中在一小部分資料上,如果我們把這些經常使用的資料快取起來,提高命中率,應該就可以減少資料庫的訪問壓力,提高響應速度。
網站使用的快取分為兩種,一種是快取在應用伺服器上的本地快取,另一種是快取在專門的分散式快取伺服器上的遠端快取。理論上,前者訪問速度更快,但受限於應用伺服器記憶體限制,所以快取資料量有限,而且會出現它和應用程式爭用記憶體的情況。遠端分散式快取(例如:memcache)可以使用叢集的方式,部署大記憶體的伺服器作為專門的快取伺服器,在理論上可以做到不受記憶體容量限制。根據這想法,網站技術架構如下圖所示。
使用快取後,資料訪問壓力有明顯緩解,但是單一應用伺服器能夠處理的請求連線也有限,在網站訪問高峰期,應用伺服器就成為了整個網站的瓶頸。
使用應用伺服器叢集改善網站的併發處理能力
我們知道,使用叢集是網站解決高併發、海量資料問題的常用手段。當一臺伺服器的處理能力儲存空間不足時,用一臺強勁的伺服器取代原服務是治標的辦法,治本的辦法應該是用多臺普通伺服器去分擔原有伺服器的訪問及儲存壓力。當然,這其中就需要解決session同步,負載均衡(策略、方法)、心跳檢測等諸多技術問題。通過多臺伺服器提供持續動態服務從而實現系統的高可用及可伸縮性。自己曾經實現的叢集方案就使得公司歐美部門在某專案競標過程中順利通過第三方獨立測試。網站技術架構如下圖所示。
通過負載均衡排程伺服器,可以將訪問請求分發到叢集終端任何一臺應用伺服器上,如果使用者數量仍不斷攀升,就可以在叢集中平滑地加入更多的應用伺服器,使應用伺服器的負載壓力不再成為整個網站的瓶頸。
資料庫讀寫分離
網站在使用快取後,使絕大部分資料讀操作訪問都可以不通過資料庫就能完成,但仍由一部分讀操作(例如:快取訪問未命中或快取過期)和全部的寫操作需要訪問資料庫,因此當網站的使用者達到相當規模後,資料庫因為負載壓力過高就可能成為網站的瓶頸。
目前大部分的主流資料庫都提供主從熱備功能,通過配置兩臺資料庫主從關係,可以將一臺資料庫伺服器的資料更新同步到另一臺伺服器上。網站利用資料庫的這個功能實現資料庫讀寫分離,從而進一步改善資料庫負載壓力。網站技術架構如下圖所示。
從上圖可以看到,應用伺服器在寫資料時,通過資料訪問模組,訪問主資料庫,主資料庫通過主從複製機制將資料更新同步到從資料庫,這樣當應用伺服器讀資料的時候,就可以通過從資料庫獲得資料。其中,資料訪問模組是為了使資料庫讀寫分離對應用透明。
使用反向代理和CDN假設網站響應
經過上述幾個技術演進,應該說能夠滿足大部分網站效能需求,但是,你要知道,咱們國家目前有多少網際網路使用者,即便12306這種網站也架不住超大使用者的同時訪問,而且由於咱們國內複雜的網路環境,不同地區的使用者訪問網站時,速度差別也極大。如果訪問一個網站時,經常出現很慢,必然造成使用者體驗差的反響,進而影響業務發展。所以,在害怕超大使用者集中訪問時,還需要想辦法留住使用者,怎麼辦呢?這就需要加速自身網站的訪問速度,主要方法有使用CDN和反向代理兩種方法。
CDN的全稱是Content Delivery Network(內容分發網路),主要含義是指將請求分配到離自己最快的伺服器。
CDN和反向代理的基本原理都是快取,區別在於CDN部署在網路提供商的機房,使使用者在請求網站服務時,可以從距離自己最近的網路提供商機房獲取資料;而反向代理則部署在網站的中心機房,當用戶請求到達中心機房後,首先訪問的伺服器是反向代理伺服器,如果反向代理伺服器中快取著使用者請求的資源,就將其直接返回給使用者。此時網站技術架構變為下圖所示。
使用CDN和反向代理的目的都是儘早返回資料給使用者,一方面加快使用者訪問速度,另一方面也減輕後端伺服器的負載壓力。
使用分散式檔案系統和分散式資料庫系統
從目前大型網站(典型的是電商網站)看,任何強大的單一伺服器都滿足不了大型網站持續增長的業務需求。儘管資料庫經過讀寫分離,且變為兩臺,但紛繁複雜的業務仍在蓬勃發展,這時若進一步優化,則需要使用分散式資料庫。檔案系統使用分散式檔案系統。此時網站技術架構變為如下圖所示。
到目前為止,分散式資料庫是網站資料庫拆分的最後手段了,只有在單表資料規模非常龐大的時候才使用。不到不得已時,網站更常用的資料庫拆分手段是業務分庫,將不同業務的資料庫部署在不同的物理伺服器上。
使用NoSQL和搜尋引擎
看這本書時,你經常會看到隨著網站業務越來越複雜這樣的文字,一般讀者或許真不知道有多複雜的業務才會搞出上述那麼牛X的架構之後還會有優化的空間。可能還有一部分讀者讀到這裡,就直接跑去最後,看看它最終的架構長什麼樣子。我讀到這裡還好,不是很被虐,因為我碰到過,知道技術這東西真能解決很多事。
一個網站的響應效率高低是使用者體驗好壞的重要指標之一。使用者對資料儲存和檢索的需求越複雜,就要求網站採用一些非關係資料庫技術(例如NoSQL)和非資料庫查詢技術(例如搜尋引擎)了。如下圖所示。
NoSQL和搜尋引擎都是源自網際網路的技術手段,對可伸縮的分散式特性具有更好的支援。應用伺服器則通過一個統一資料訪問模組訪問各種資料,減輕應用程式管理諸多資料來源的麻煩。
業務拆分
大型電商網站為了應對日益複雜的業務場景,還通過使用分而治之的手段將整個網站業務分成不同的產品線交由不同的業務團隊負責,例如首頁、商鋪、訂單、買家、賣家等均為不同產品線。
從技術上而言,會根據產品線劃分,將一個網站拆分成許多不同的應用,每個應用獨立部署維護。應用之間可以通過超連結建立關係,還可以通過訊息佇列(例如:RabbitMQ,Kafka,ActiveMQ或Apollo)進行資料分發,最多的還是通過訪問同一個資料儲存系統來構成一個關聯的完整系統。這裡典型的架構是SOA的場景。WebService及SOA的架構也會出現服務太多過亂的情況,後來有引入Dubbo和ZooKeeper來進行服務治理和發現的。如下圖所示。
分散式服務
當業務拆分越來越小,儲存系統越來越大,應用系統的整體複雜度呈指數級增加,部署維護越來越困難。由於所有應用要和所有資料庫系統連線,在數萬臺伺服器規模的網站中,這些連線的數目是伺服器規模的平方,導致存資料庫連線資源不足,拒絕服務。
既然每一個應用系統都需要執行許多相同的業務操作,比如使用者管理、商品管理等,那麼可以將這些共用的業務提取出來,獨立部署。由這些可複用的業務連線資料庫,提供共用業務服務,而應用系統只需要管理使用者介面,通過分散式伺服器呼叫共用業務服務完成具體業務操作。如下圖所示。
在這些架構演進過程中,大多數技術問題都可以得到解決,類似跨資料中心的實時資料同步和具體網站業務相關的問題也都可以通過改進現有技術架構來解決。
大型網站架構解決了海量資料的管理和高併發事務的處理,也可以將這些解決方案應用到網站自身以外的業務上去。目前很多大型網站都開始建立雲技術平臺,將計算作為一種整合資源出售,讓中小網站不需要再關心技術架構問題,而只需按需付費,就可以獲得更大儲存空間及計算資源。