【讀書筆記】網站伸縮性架構-永無止境

6、伸縮性-永無止境

架構的伸縮性設計

不同功能進行物理分離實現伸縮

縱向分離(分層後分離)
橫向分離(業務分割後分離)
在這裏插入圖片描述
在這裏插入圖片描述

單一功能通過集羣規模實現伸縮

當一頭牛拉不動車的時候,不要去尋找一頭更強壯的牛,而是用兩頭牛來拉車。

應用服務器集羣的伸縮性設計

HTTP 重定向負載均衡

在這裏插入圖片描述
根據請求,計算一個服務器地址,利用 HTTP 302 重定向到服務器地址。
優點:
比較簡單。
缺點:
瀏覽器需要兩次請求服務器才能完成一次訪問,性能較差;
重定向服務器自身的處理能力可能成爲性能瓶頸;
302 重定向可能被搜索引擎判斷爲 SEO 作弊,降低搜索排名。

DNS 域名解析負載均衡

在這裏插入圖片描述
在 DNS 服務器中配置多個 A 記錄,如: www.xxx.com IN A 114.100.80.1 和 www.xxx.com IN A 114.100.80.2。每次域名解析請求都會根據負載均衡算法計算一個不同的 IP 地址返回。
優點:
負載均衡工作轉交給 DNS,省去了一些工作內容。
DNS 還支持基於地理位置的域名解析。
缺點:
DNS 多級解析,每一級 DNS 都可能緩存 A 記錄,當某臺服務器下線後,即使修改了 A 記錄,也得等一會才能生效。

可以部分使用 DNS 域名解析,解析作爲第一級負載均衡手段,即解析得到的一組服務器並不是真正提供 Web 服務的物理服務器,而是同樣提供負載均衡的內部服務器。

反向代理負載均衡

在這裏插入圖片描述
反向代理服務器轉發請求在 HTTP 協議層面,因此也稱爲 應用層負載均衡。
優點:
和反向代理服務器功能集成在一起,部署簡單。
缺點:
反向代理服務器是所有請求和響應的中轉站,性能可能會成爲瓶頸。

IP 負載均衡

在這裏插入圖片描述
SNAT 源地址轉換!
優點:
IP 負載均衡在內核進程中完成數據分發,比反向代理負載均衡(在應用層分發)有更好的性能;
缺點:
所有請求和響應都要經過負載均衡服務器,集羣最大相應數據屯獨立受制於負載均衡服務器網卡帶寬;

數據鏈路負載均衡

在這裏插入圖片描述
在通信協議的數據鏈路層修改 mac 地址進行負載均衡。
這種負載均衡方式又稱作直接路由方式(DR)。
也稱爲三角模式。
在 Linux 上比較好的開源產品是 LVS(Linux Virtual Server)

負載均衡算法

負載均衡服務器的實現可以分爲 2 個部分:
1、根據負載均衡算法和 Web 服務器列表得到集羣中一臺 Web 服務器的地址。
2、將請求數據發送到該地址對應的 Web 服務器上。

輪詢(Round Robin,RR)

適用於所有服務器硬件都相同的場景。

加權輪詢(Weighted Round Robin,WRR)

根據硬件性能,高性能服務器能分配更多請求。

隨機(Random)

簡單實用,隨機數本身就很均衡。
也可以改一改成爲加權隨機法。

最少連接(Least Connections)

記錄每個服務器正在處理的連接數(請求數),新請求發給連接數最少的那個。
同樣可以實現個加權最少連接。

源地址散列(Source Hashing)

一個 IP 地址進行 Hash 得到應用服務器地址,這樣來自同一個 IP 地址的請求總在同一個服務器上處理,該請求的上下文信息可以存儲在這臺服務器上,在一個會話週期內複用,從而實現會話粘滯。

分佈式緩存集羣的伸縮性設計

Memcached 分佈式緩存集羣的訪問模型

set(key, data)、get(key)
路由根據 key 計算對應應該從哪臺服務器寫緩存,從哪臺服務器讀緩存。

Memcached 分佈式緩存集羣的伸縮性挑戰

對於集羣的管理,路由算法至關重要,決定着究竟該訪問集羣中的哪臺服務器。
簡單的路由算法就是餘數 Hash。
對於餘數 Hash,當集羣需要擴容的時候,事情就比較糟糕了。
假設 3 臺緩存服務器需要擴容到 4 臺,更改服務器列表,依然使用餘數 Hash,用 4/key 的 Hash 值大約有 75%(3/4) 不能正確命中,隨着服務器集羣規模的增大,這個比例直線上升!
當 100 臺集羣中增加一臺,不能命中的概率是 99%( n/(n+1) )。

大部分的業務數據讀操作請求事實上是通過緩存獲取的,只有少量的操作請求會訪問數據庫。
當大量的緩存出現不能命中時,對於數據庫的壓力就很大了,甚至宕機。

一種解決方法就是在網站訪問了最少的時候進行緩存服務器集羣擴容,然後通過模擬請求的方法來預熱緩存。
另一種方法就是通過下面的算法了!

分佈式緩存的一致性 Hash 算法

一致性 Hash 算法通過一個叫做一致性 Hash 環的數據結構實現 KEY 到緩存服務器的 Hash 映射。
![image.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlLzAvMjAyMC9wbmcvNTU2MTI0LzE1OTE1MTM2NzA1OTAtZDU0NmMyMzEtOTMwZS00OTNjLWFkZGItNDc1ZTQ2M2ZiMTY1LnBuZw?x-oss-process=image/format,png#align=left&display=inline&height=231&margin=[object Object]&name=image.png&originHeight=922&originWidth=918&size=115943&status=done&style=none&width=230)
具體算法過程爲:
先構造一個長度爲 2^32 的整數環,這個環被稱爲一致性 Hash 環。
根據節點名稱的 Hash 值(其分佈範圍爲[0, 2^32-1])將緩存服務器節點放置在這個 Hash 環上。
然後根據需要緩存的數據 KEY 的值計算得到其 Hash 值(分佈範圍同上)。
然後在 Hash 環上順時針找舉例這個 KEY 的 Hash 值最近的緩存服務器節點,完成 KEY 服務器的 Hash 映射查找。

當緩存服務器集羣需要擴容的時候,只需要將新加入的節點名稱(NODE3)的 Hash 值放入一致性 Hash 環中,由於 KEY 是順時針查找舉例其最近的節點,因此新加入的節點隻影響整個環中的一小段。
![image.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlLzAvMjAyMC9wbmcvNTU2MTI0LzE1OTE1MTQyNzYxODgtZTdmNTE2OWItYmExYi00ODA5LWIxZmEtZmM3ZmExODgxZDI0LnBuZw?x-oss-process=image/format,png#align=left&display=inline&height=251&margin=[object Object]&name=image.png&originHeight=1002&originWidth=1026&size=138950&status=done&style=none&width=257)
3臺 -> 4臺擴容時候的命中率是 75%,遠高於餘數 Hash 的 25%。

在具體應用中,這個長度爲 2^32 的一致性 Hash 環通常使用二叉查找樹實現,Hash 查找過程實際上是在二叉查找樹中查找**不小於查找數的最小數值,**這個數的最左葉子節點和最右葉子節點連接構成環。

但是!這個過程還存在一些小問題!

新加入的節點 NODE3 隻影響了原來的節點 NODE1,也就是說一部分原來需要訪問 NODE1 的緩存數據現在需要訪問 NODE3(概率上市 50%)。
但是原來的節點 NODE0 和 NODE2 不受影響,這就意味着 NODE0 和 NODE2 緩存數據量和負載壓力是 NODE1 和 NODE3 的兩倍。
如果這 4 臺機器性能是一樣的,那麼這種結果不是想要的。

怎麼辦?

計算機的任何問題都可以通過增加一個虛擬層來解決!
計算機硬件、計算機網絡、計算機軟件都莫過於此。
計算機網絡7層,每一層可以看做是下一層的虛擬層;計算機操作系統可以看做是硬件的虛擬層;JVM 可以看作是操作系統的虛擬層;分層軟件架構事實上也是如此。

將每臺物理緩存服務器虛擬爲一組虛擬緩存服務器,將虛擬服務器的 Hash 值放置在 Hash 環上,KEY 在環上先找到虛擬服務器節點,再得到物理服務器信息。

這樣在新加入物理服務器節點時,是將一組虛擬節點加入環中,如果虛擬節點的樹木足夠多,這組虛擬節點將會影響同樣多樹木的已經在換上存在的虛擬節點,這些已經存在的虛擬節點又對應不同的物理節點。
最終結果是:新加入一臺緩存服務器,將會較爲均勻的影響原來及羣衆已經存在的所有服務器,也就是說分攤原有緩存服務器集羣中所有服務器的一小部分負載。

![image.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlLzAvMjAyMC9wbmcvNTU2MTI0LzE1OTE1MTU0MDY5MzktNTExZmIwNmMtODIxYS00M2NjLTk3NWEtY2RlZmU3MWJiZDhmLnBuZw?x-oss-process=image/format,png#align=left&display=inline&height=253&margin=[object Object]&name=image.png&originHeight=1010&originWidth=1370&size=112263&status=done&style=none&width=343)
如上圖,加入 NODE3 對應的一組虛擬節點爲 V30 V32 V32,加入到一致性 Hash 環上後,影響 V01 V12 V22
這三個被影響的虛擬節點對應 NODE0 NODE1 NODE2 三個物理節點。
最終加入一個節點,影響三個物理節點,理想情況下,每個物理節點收到影響的緩存數據量是 1/4 (x/ (x+n)),N 爲原物理節點數,X 爲新加入物理節點數。也就是及羣衆已經被緩存的數據有 75% 可以被命中。

理論上虛擬節點數越多,物理節點之間的負載就越均衡。
但是太多影響性能,太少負載不均衡,一般來說經驗是 150,根據集羣規模和均衡的精度需求,具體對待。

數據存儲服務器集羣的伸縮性設計

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

分庫分表,質數。

NoSQL 數據庫的伸縮性設計

NoSQL 更關注高可用性和可伸縮性。
捨棄了以關係代數爲基礎的結構化查詢語言(SQL)和事務一致性保證(ACID)。


EOF!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章