【技術架構—要點】伸縮性架構

所謂系統的伸縮性是指不須要改變系統的軟硬件設計,僅僅經過改變部署的服務器數量就能夠擴大或者縮小系統的服務處理能力。算法

基礎設計

在應用系統漸進式的演化過程當中,最重要的技術手段就是使用服務器集羣,經過不斷地向集羣中添加服務器來加強整個集羣的處理能力。數據庫

通常說來,系統的伸縮性設計可分紅兩類,一類是根據功能進行物理分離實現伸縮,一類是單一功能經過集羣實現伸縮。前者是不一樣的服務器部署不一樣的服務,提供不一樣的功能;後者是集羣內的多臺服務器部署相同的服務,提供相同的功能。segmentfault

在應用系統發展的早期,經過增長服務器提升處理能力時,新增服務器老是從現有服務器中分離出部分功能和服務。具體又能夠分紅縱向分離和橫向分離兩種狀況,縱向分離也即業務分層,橫向分離則是業務拆分。瀏覽器

將不一樣功能分離部署能夠實現必定程度的伸縮性,可是隨着訪問量的逐步增長,即便分離到最小粒度,單一的服務器也不能知足業務規模的要求。所以必須使用服務器集羣,即將相同服務部署在多臺服務器上構成一個集羣總體對外提供服務。緩存

應用層設計

應用服務器應該設計成無狀態的,若是將部署有相同應用的服務器組成一個集羣,每次用戶請求均可以發送到集羣中任意一臺服務器上去處理。這樣只要能將用戶請求按照某種規則分發到集羣的不一樣服務器上,就能夠構成一個應用服務器集羣。服務器

這個請求分發裝置就是所謂的負載均衡器。負載均衡是網站必不可少的基礎技術手段,不但能夠改善網站的可用性,同時還能夠實現網站的伸縮性。具體的技術實現也多種多樣,基礎技術不外如下幾種。網絡

HTTP重定向

HTTP重定向服務器是一臺普通的應用服務器,其惟一的功能就是根據用戶的HTTP請求計算一臺真實的Web服務器地址,並將該Web服務器地址寫入HTTP重定向響應中(響應狀態碼302)返回給用戶瀏覽器數據結構

這種負載均衡方案的優勢是比較簡單。缺點是瀏覽器須要兩次請求服務器才能完成一次訪問,性能較差;重定向服務器自身的處理能力有可能成爲瓶頸,整個集羣的伸縮性規模有限;使用302響應碼重定向,有可能使搜索引擎判斷爲SEO做弊,下降搜索排名。所以這種方案不多見。架構

DNS解析

咱們能夠在DNS服務器中爲應用網址註冊多條A記錄,這樣的話,每次域名解析請求都會根據負載均衡算法計算一個不一樣的IP地址返回,A記錄中配置的多個服務器就構成一個集羣,實現了負載均衡。負載均衡

DNS域名解析負載均衡的優勢是將負載均衡的工做轉交給DNS,省掉了網站管理維護負載均衡服務器的麻煩,同時許多DNS還支持基於地理位置的域名解析,即會將域名解析成距離用戶地理最近的一個服務器地址,這樣可加快用戶訪問速度。

可是DNS域名解析負載均衡也有缺點,DNS是多級解析,每一級DNS均可能緩存A記錄,當下線某臺服務器後,即便修改了DNS的A記錄,要使其生效也須要較長時間,這段時間,DNS依然會將域名解析到已經下線的服務器,致使用戶訪問失敗;並且DNS負載均衡的控制權在域名服務商那裏,網站沒法對其作更多改善和更強大的管理。

大型網站老是部分使用DNS域名解析,利用域名解析做爲第一級負載均衡手段。域名解析獲得的一組服務器並非實際提供Web服務的物理服務器,而是一樣提供負載均衡服務的內部服務器,這組內部負載均衡服務器再進行負載均衡,將請求分發到真實的Web服務器上。

反向代理

以前咱們提到能夠利用反向代理緩存資源,以改善網站性能。同時大多數反向代理服務器還提供負載均衡的功能,管理一組Web服務器,將請求根據負載均衡算法轉發到不一樣Web服務器上,Web服務器處理完成的響應也須要經過反向代理服務器返回給用戶。

因爲反向代理服務器轉發請求在HTTP協議層面,所以也叫應用層負載均衡。其優勢是和反向代理服務器功能集成在一塊兒,部署簡單。缺點是反向代理服務器是全部請求和響應的中轉站,其性能可能會成爲瓶頸。

IP負載均衡

在網絡層,能夠經過修改請求目標地址進行負載均衡。用戶請求數據包到達負載均衡服務器後,負載均衡服務器根據負載均衡算法計算獲得一臺真實Web服務器地址,而後將數據包的目的IP地址修改成該地址。真實Web應用服務器處理完成後,響應數據包回到負載均衡服務器,負載均衡服務器再將數據包源地址修改成自身的IP地址發送給用戶瀏覽器。

這裏的關鍵在於真實物理Web服務器響應數據包如何返回給負載均衡服務器。一種方案是負載均衡服務器在修改目的IP地址的同時修改源地址,將數據包源地址設爲自身IP,即源地址轉換(SNAT),這樣Web服務器的響應會再回到負載均衡服務器;另外一種方案是將負載均衡服務器同時做爲真實物理服務器集羣的網關服務器,這樣全部響應數據都會到達負載均衡服務器。

IP負載均衡在內核進程完成數據分發,較反向代理負載均衡(在應用程序中分發數據)有更好的處理性能。可是因爲全部請求響應都須要通過負載均衡服務器,集羣的最大響應數據吞吐量不得不受制於負載均衡服務器網卡帶寬。

那麼,能不能讓負載均衡服務器只分發請求,而使響應數據從真實物理服務器直接返回給用戶呢?

數據鏈路層負載均衡

顧名思義,數據鏈路層負載均衡是指在通訊協議的數據鏈路層修改mac地址進行負載均衡。負載均衡數據分發過程當中不修改IP地址,只修改目的mac地址,經過配置真實物理服務器集羣全部機器虛擬IP和負載均衡服務器IP地址一致,從而達到不修改數據包的源IP地址和目的IP地址就能夠進行數據分發的目的。

因爲實際處理請求的真實物理服務器IP和數據請求目的IP一致,不須要經過負載均衡服務器進行地址轉換,可將響應數據包直接返回給用戶瀏覽器,避免負載均衡服務器網卡帶寬成爲瓶頸。這種負載均衡方式又稱做直接路由方式(DR)。

image.png

如圖所示,用戶請求到達負載均衡服務器114.100.80.10後,負載均衡服務器將請求數據的目的mac地址修改成00:0c:29:d2,因爲Web服務器集羣全部服務器的虛擬IP地址都和負載均服務器的IP地址相同,所以數據能夠正常傳輸到達mac地址00:0c:29:d2對應的服務器,該服務器處理完成後發送響應數據到網站的網關服務器,網關服務器直接將該數據包發送到用戶瀏覽器,響應數據不須要經過負載均衡服務器。

數據鏈路層負載均衡是目前使用較廣的一種負載均衡手段。在Linux平臺上最好的鏈路層負載均衡開源產品是LVS(Linux Virtual Server)。

負載均衡算法

前面描述瞭如何將請求數據發送到Web服務器,而具體的負載均衡算法一般有如下幾種:

  • 輪詢(Round Robin,RR):全部請求被依次分發到每臺應用服務器上,適合於全部服務器硬件都相同的場景。
  • 加權輪詢(Weighted Round Robin,WRR):根據應用服務器硬件性能的狀況,在輪詢的基礎上,按照配置的權重將請求分發到每一個服務器。
  • 隨機(Random):請求被隨機分配到各個應用服務器,在許多場合下,這種方案都很簡單實用。即便應用服務器硬件配置不一樣,也可使用加權隨機算法。
  • 最少鏈接(Least Connections):記錄每一個應用服務器正在處理的鏈接數(請求數),將新到的請求分發到最少鏈接的服務器上。一樣,也能夠實現加權最少鏈接。
  • 源地址散列(Source Hashing):根據請求來源的IP地址進行Hash計算,獲得應用服務器,這樣來自同一個IP地址的請求總在同一個服務器上處理。

緩存設計

和全部服務器都部署相同應用的應用服務器集羣不一樣,分佈式緩存服務器集羣中不一樣服務器中緩存的數據各不相同,緩存訪問請求不能夠在緩存服務器集羣中的任意一臺處理,必須先找到緩存有須要數據的服務器,而後才能訪問。這個特色會嚴重製約分佈式緩存集羣的伸縮性設計,由於新上線的緩存服務器沒有緩存任何數據,而已下線的緩存服務器還緩存着網站的許多熱點數據。

必須讓新上線的緩存服務器對整個分佈式緩存集羣影響最小,也就是說新加入緩存服務器後應使整個緩存服務器集羣中已經緩存的數據儘量還被訪問到,這是分佈式緩存集羣伸縮性設計的最主要目標。

路由算法

在分佈式緩存服務器集羣中,對於服務器集羣的管理,路由算法相當重要,和負載均衡算法同樣,決定着究竟該訪問集羣中的哪臺服務器。

餘數Hash算法

餘數Hash是最簡單的一種路由算法:用服務器數目除以緩存數據KEY的Hash值,餘數爲服務器列表下標編號。因爲HashCode具備隨機性,所以使用餘數Hash路由算法可保證緩存數據在整個服務器集羣中比較均衡地分佈。

對餘數Hash路由算法稍加改進,就能夠實現和負載均衡算法中加權負載均衡同樣的加權路由。事實上,若是不須要考慮緩存服務器集羣伸縮性,餘數Hash幾乎能夠知足絕大多數的緩存路由需求。

可是,當分佈式緩存集羣須要擴容的時候,會出現嚴重的問題。很容易就能夠計算出,若是由3臺服務器擴容至4臺服務器,大約有75%(3/4)被緩存了的數據不能正確命中,隨着服務器集羣規模的增大,這個比例線性上升。當100臺服務器的集羣中加入一臺新服務器,不能命中的機率是99%(N/(N+1))。

一種解決辦法是在網站訪問量最少的時候擴容緩存服務器集羣,這時候對數據庫的負載衝擊最小。而後經過模擬請求的方法逐漸預熱緩存,使緩存服務器中的數據從新分佈。可是這種方案對業務場景有要求,還須要選擇特定的時段,要求較爲嚴苛。

一致性Hash算法

一致性Hash算法經過一個叫做一致性Hash環的數據結構實現KEY到緩存服務器的Hash映射,如圖所示。

image.png

具體算法過程爲:先構造一個長度爲0~2³²的整數環(這個環被稱做一致性Hash環),根據節點名稱的Hash值(其分佈範圍一樣爲0~2³²)將緩存服務器節點放置在這個Hash環上。而後根據須要緩存的數據的KEY值計算獲得其Hash值(其分佈範圍也一樣爲0~2³²),而後在Hash環上順時針查找距離這個KEY的Hash值最近的緩存服務器節點,完成KEY到服務器的Hash映射查找。

當緩存服務器集羣須要擴容的時候,只須要將新加入的節點名稱(NODE3)的Hash值放入一致性Hash環中,因爲KEY是順時針查找距離其最近的節點,所以新加入的節點隻影響整個環中的一小段,如圖6中深色一段。

image.png

加入新節點NODE3後,原來的KEY大部分還能繼續計算到原來的節點,只有KEY三、KEY0從原來的NODE1從新計算到NODE3。這樣就能保證大部分被緩存的數據還能夠繼續命中。

具體應用中,這個長度爲2³²的一致性Hash環一般使用二叉查找樹實現,Hash查找過程其實是在二叉查找樹中查找不小於查找數的最小數值。固然這個二叉樹的最右邊葉子節點和最左邊的葉子節點相鏈接,構成環。

可是,上述算法還存在一個小小的問題。假設本來3臺服務器的負載大體相等,新加入的節點NODE3只分擔了節點NODE1的部分負載,這就意味着NODE0和NODE2緩存數據量和負載壓力比NODE1與NODE3的大,從機率上來講大約是2倍。這種結果顯然不是咱們想要的。

解決辦法也很簡單,計算機的任何問題均可以經過增長一個虛擬層來解決。解決上述一致性Hash算法帶來的負載不均衡問題,也能夠經過使用虛擬層的手段:將每臺物理緩存服務器虛擬爲一組虛擬緩存服務器,將虛擬服務器的Hash值放置在Hash環上,KEY在環上先找到虛擬服務器節點,再獲得物理服務器的信息

這樣新加入物理服務器節點時,是將一組虛擬節點加入環中,若是虛擬節點的數目足夠多,這組虛擬節點將會影響一樣多數目的已經在環上存在的虛擬節點,這些已經存在的虛擬節點又對應不一樣的物理節點。最終的結果是:新加入一臺緩存服務器,將會較爲均勻地影響原來集羣中已經存在的全部服務器。如圖所示。

image.png

顯然每一個物理節點對應的虛擬節點越多,各個物理節點之間的負載越均衡,新加入物理服務器對原有的物理服務器的影響越保持一致,可是太多又會影響性能。那麼在實踐中,一臺物理服務器虛擬爲多少個虛擬服務器節點合適呢?通常說來,經驗值是150,固然根據集羣規模和負載均衡的精度需求,這個值應該根據具體狀況具體對待。

數據存儲層設計

數據存儲服務器集羣的伸縮性對數據的持久性和可用性提出了更高的要求,由於數據存儲服務器在任何狀況下都必須保證數據的可用性和正確性。

關係數據庫集羣的伸縮性設計

目前,市面上主要的關係數據都支持數據複製功能,使用這個功能能夠對數據庫進行簡單伸縮。下圖爲使用數據複製的MySQL集羣伸縮性方案。

image.png

在這種架構中,多臺MySQL實例有主從之分,數據寫操做都在主服務器上,由主服務器將數據同步到集羣中其餘從服務器,數據讀操做及數據分析等離線操做在從服務器上進行。

除了數據庫主從讀寫分離,前面提到的業務分割模式也能夠用在數據庫,不一樣業務數據表部署在不一樣的數據庫集羣上,即俗稱的數據分庫。

在大型系統中,即便進行了分庫和主從複製,對一些單表數據仍然很大的表,還須要進行分片,將一張表拆開分別存儲在多個數據庫中。目前市場上經常使用的分庫分表的中間件是Mycat。

相比關係數據庫自己功能的強大,目前各種分庫分表中間件的功能都顯得很是簡陋,限制了關係數據庫某些功能的使用。可是當網站業務面臨不停增加的海量業務數據存儲壓力時,又不得不利用分佈式關係數據庫的集羣伸縮能力,這時就必須從業務上回避分佈式關係數據庫的各類缺點:避免事務或利用事務補償機制代替數據庫事務;分解數據訪問邏輯避免JOIN操做等。

延伸閱讀:
【分佈式—要點】數據複製
【分佈式—要點】數據分區

相關文章
相關標籤/搜索