網站架構瓶頸解決方案(發展歷程)
本篇文章參考《大型網站技術架構》,夾雜了一些個人理解,本人渣渣,如有不合理或不全面之處,還請各位指出,不勝感激。
首先,個人認為,網站的架構發展還是根據自家的瓶頸來改進演變,並無“一種架構演變方式打遍天下”一說,首先要找到自家網站的瓶頸,然後根據瓶頸來設計對策方案為好。
下面所述為演變方案之一:
1.初始階段(單機架構)
有的網站(如後臺管理系統),性質就決定了併發量,還有的2C的網站在初始階段,並沒有多大的訪問量,因此一臺伺服器就綽綽有餘(可用性會另說),這時的架構比較簡單,我們稱之為單機架構,如圖
很多大型網站,都經歷過這個階段
2.服務分離
隨著使用者量的增多,網站逐漸出現效能瓶頸,這時我們可將應用服務和資料服務分離。
我們可將應用程式、檔案服務和資料服務分別部署在不同的伺服器上。
不同的服務可選擇不同效能的伺服器,比如應用程式要處理大量計算,我們可選擇更快的CPU,資料庫伺服器可選擇更大的磁碟和記憶體,檔案服務可選擇更大的磁碟。
3.資料庫瓶頸
讀請求和寫請求都落在資料庫伺服器上,漸漸地,資料庫伺服器會不堪重負,為了解決這個問題,我們可以採用三個方案(或都採用,依據實際情況來定)
快取
網站訪問也存在二八定律:80%的業務訪問集中在20%的熱點資料上。如:淘寶買家瀏覽的商品集中在銷量多、評價好的商品上;微博的熱搜等。
既然大部分訪問集中在小部分資料上,我們可把這一小部分資料(熱點資料)快取在記憶體中,即可減少資料庫訪問,改善網站效能。
快取有兩種方式:
- 快取在應用伺服器的本地快取中(訪問快,但會佔用應用伺服器的快取,因此不能快取太多)
- 快取在專門的分散式快取伺服器上(要經過網路遠端訪問,但可快取的東西較多)
讀寫分離
目前大部分主流資料庫都提供主從熱備功能,通過配置兩臺資料庫的主從關係,可以將一臺資料庫伺服器的資料更新同步到另一臺伺服器上。我們可以利用這一功能,實現資料庫的讀寫分離,從而改善資料庫負載壓力。
應用伺服器在寫資料的時候,訪問主資料庫,主資料庫通過主從複製機制將資料更新同步到從資料庫,這樣應用伺服器讀資料的時候,就可以通過從資料庫獲得資料。
為了便於應用程式訪問讀寫分離後的資料庫,通常在應用伺服器端使用專門的資料訪問模組,使資料庫讀寫分離對應用透明。
分庫分表
分庫分表是資料庫拆分的最後手段。
分庫:將單個數據庫按需求拆分(如:訂單庫、商品庫等)
分表:在單表資料規模非常龐大的時候(千萬級別),我們可進行分表,如按時間分等,比如餓了麼只能看到近一年的訂單,猜想它是進行了按訂單時間定時分表的操作。
4.應用伺服器瓶頸
之前有人說過,一個請求大概佔2M記憶體。
隨著請求數量的增加,應用伺服器可能會出現效能瓶頸,這時我們有兩種方式應對:
垂直擴充套件(不推薦)
一臺伺服器出現效能瓶頸,就更換記憶體更大、CPU更快或是磁碟更大的伺服器,這種擴充套件方式,我們稱之為垂直擴充套件。
但是,我們使用者數量可能是不設限的,我們不能丹丹依靠於單臺硬體,不會有無限大的記憶體、硬碟,無限快的CPU來滿足我們的需求,因此,這種擴充套件方式較為僵化,個人不推薦使用。
水平擴充套件
一臺伺服器出現瓶頸?那就多來幾個伺服器!通過負載均衡伺服器,可將來自使用者瀏覽器的訪問請求分發到應用伺服器叢集中的任意一臺伺服器上。
再有瓶頸的情況,可通過再加入伺服器的方式解決。
5.加速網站響應--反向代理和CDN
本質上,反向代理和CDN都是快取。
CDN部署在網路提供商的機房,使用者在請求網站服務時,可以從距離自己最近的網路提供商機房獲取資料。
反向代理部署在網站的中心機房,當用戶請求到達中心機房後,首先訪問的伺服器是反向代理伺服器,如果反向代理伺服器中快取著使用者請求的資源,求將其直接返回給使用者。
6.搜尋引擎
我們主要講一講垂直化搜尋引擎,這裡所說的垂直化搜尋引擎,與大家所熟知的百度和Google存在一些差別。
垂直化搜尋引擎主要針對企業內部的自有資料的檢索,而不是像Google和百度等搜尋引擎平臺,採用爬蟲對全網資料進行爬取,建立索引並提供給使用者進行檢索。
在我們的分散式架構中,垂直化搜尋引擎是很重要的一個角色,它既能滿足使用者對於全文檢索、模糊匹配的需求,解決資料庫like查詢效率低下的問題;又能夠解決分散式環境下,由於採用分庫分表或者使用NoSQL資料庫,導致無法進行多表關聯或者進行復雜查詢的問題。
搜尋引擎的幾個重要概念:
倒排索引:又稱反向索引,幾乎所有的搜尋引擎都會用到倒排索引。它將文件中的詞作為關鍵字建立詞與文件的對映關係,通過對倒排索引的檢索,可以根據詞快速獲取包含這個詞的文件列表。
分詞:又稱切詞,即將句子或者段落進行切割,從中提取出包含固定語義的詞。對於英語來說較為容易,因為英語的基本單位就是單詞。但是對於中文來說,就比較困難了,常用的中文分詞器包括一元分詞(以字為單位切分)、二元分詞(以兩個字為單位切分)、詞庫分詞(用詞庫中定義的詞來進行切分)等。
索引的構建分為這樣幾個過程:通過指定的資料格式,將文件傳遞給分詞器進行分詞,然後通過索引寫入工具將索引寫入指定的目錄。
7.非同步
我們寫程式碼,很重要的一點是降低耦合性,事物間的直接關係越少,就越少彼此影響,越可以獨立發展。
在大型網站中,系統解耦合很重要的一個手段是非同步呼叫,我們可以使用訊息佇列(如kafka、ActiveMQ等)實現非同步呼叫。
好處如下:
提高系統可用性:消費者伺服器發生故障,資料會在訊息佇列中堆積,對生產者無影響,系統整體表現無異常,待消費者故障恢復,繼續消費訊息佇列中的資料。
加快網站響應速度:生產者在將資料寫入訊息佇列即可返回,響應延遲減少。
消除併發訪問高峰:“削峰填谷”面熟的就是這個場景,可以降低高峰時期的負載。
8.業務拆分
隨著網站越來越複雜,部署維護變得越來越困難,據說某知名網約車公司專案啟動要達十分鐘之久。
於是我們可將業務進行拆分,如電商系統,我們可以將業務拆分為訂單、商品等,一個部門專門負責一個部分,這樣上線、維護都會簡單一些,服務之間通過遠端呼叫(現有許多成熟的RPC框架:WebService、dubbo等)完成業務操作。