咱們來看看解決問題的方案:前端
一、第一個問題便是負載均衡的問題,通常有5種解決方案:java
一、http重定向。HTTP重定向就是應用層的請求轉發。用戶的請求其實已經到了HTTP重定向負載均衡服務器,服務器根據算法要求用戶重定向,用戶收到重定向請求後,再次請求真正的集羣mysql
優勢:簡單。nginx
缺點:性能較差。web
二、DNS域名解析負載均衡。DNS域名解析負載均衡就是在用戶請求DNS服務器,獲取域名對應的IP地址時,DNS服務器直接給出負載均衡後的服務器IP。redis
優勢:交給DNS,不用咱們去維護負載均衡服務器。算法
缺點:當一個應用服務器掛了,不能及時通知DNS,並且DNS負載均衡的控制權在域名服務商那裏,網站沒法作更多的改善和更強大的管理。spring
三、反向代理服務器。在用戶的請求到達反向代理服務器時(已經到達網站機房),由反向代理服務器根據算法轉發到具體的服務器。經常使用的apache,nginx均可以充當反向代理服務器。sql
優勢:部署簡單。數據庫
缺點:代理服務器可能成爲性能的瓶頸,特別是一次上傳大文件。
四、IP層負載均衡。在請求到達負載均衡器後,負載均衡器經過修改請求的目的IP地址,從而實現請求的轉發,作到負載均衡。
優勢:性能更好。
缺點:負載均衡器的寬帶成爲瓶頸。
五、數據鏈路層負載均衡。在請求到達負載均衡器後,負載均衡器經過修改請求的mac地址,從而作到負載均衡,與IP負載均衡不同的是,當請求訪問完服務器以後,直接返回客戶。而無需再通過負載均衡器。
二、第二個問題便是集羣調度算法問題,常見的調度算法有10種。
一、rr 輪詢調度算法。顧名思義,輪詢分發請求。
優勢:實現簡單
缺點:不考慮每臺服務器的處理能力
二、wrr 加權調度算法。咱們給每一個服務器設置權值weight,負載均衡調度器根據權值調度服務器,服務器被調用的次數跟權值成正比。
優勢:考慮了服務器處理能力的不一樣
三、sh 原地址散列:提取用戶IP,根據散列函數得出一個key,再根據靜態映射表,查處對應的value,即目標服務器IP。過目標機器超負荷,則返回空。
四、dh 目標地址散列:同上,只是如今提取的是目標地址的IP來作哈希。
優勢:以上兩種算法的都能實現同一個用戶訪問同一個服務器。
五、lc 最少鏈接。優先把請求轉發給鏈接數少的服務器。
優勢:使得集羣中各個服務器的負載更加均勻。
六、wlc 加權最少鏈接。在lc的基礎上,爲每臺服務器加上權值。算法爲:(活動鏈接數*256+非活動鏈接數)÷權重 ,計算出來的值小的服務器優先被選擇。
優勢:能夠根據服務器的能力分配請求。
七、sed 最短時間望延遲。其實sed跟wlc相似,區別是不考慮非活動鏈接數。算法爲:(活動鏈接數+1)*256÷權重,一樣計算出來的值小的服務器優先被選擇。
八、nq 永不排隊。改進的sed算法。咱們想一下什麼狀況下才能「永不排隊」,那就是服務器的鏈接數爲0的時候,那麼假若有服務器鏈接數爲0,均衡器直接把請求轉發給它,無需通過sed的計算。
九、LBLC 基於局部性的最少鏈接。均衡器根據請求的目的IP地址,找出該IP地址最近被使用的服務器,把請求轉發之,若該服務器超載,最採用最少鏈接數算法。
十、LBLCR 帶複製的基於局部性的最少鏈接。均衡器根據請求的目的IP地址,找出該IP地址最近使用的「服務器組」,注意,並非具體某個服務器,而後採用最少鏈接數從該組中挑出具體的某臺服務器出來,把請求轉發之。若該服務器超載,那麼根據最少鏈接數算法,在集羣的非本服務器組的服務器中,找出一臺服務器出來,加入本服務器組,而後把請求轉發之。
三、第三個問題是集羣模式問題,通常3種解決方案:
一、NAT:負載均衡器接收用戶的請求,轉發給具體服務器,服務器處理完請求返回給均衡器,均衡器再從新返回給用戶。
二、DR:負載均衡器接收用戶的請求,轉發給具體服務器,服務器出來玩請求後直接返回給用戶。須要系統支持IP Tunneling協議,難以跨平臺。
三、TUN:同上,但無需IP Tunneling協議,跨平臺性好,大部分系統均可以支持。
四、第四個問題是session問題,通常有4種解決方案:
一、Session Sticky。session sticky就是把同一個用戶在某一個會話中的請求,都分配到固定的某一臺服務器中,這樣咱們就不須要解決跨服務器的session問題了,常見的算法有ip_hash法,即上面提到的兩種散列算法。
優勢:實現簡單。
缺點:應用服務器重啓則session消失。
二、Session Replication。session replication就是在集羣中複製session,使得每一個服務器都保存有所有用戶的session數據。
優勢:減輕負載均衡服務器的壓力,不須要要實現ip_hasp算法來轉發請求。
缺點:複製時寬帶開銷大,訪問量大的話session佔用內存大且浪費。
三、Session數據集中存儲:session數據集中存儲就是利用數據庫來存儲session數據,實現了session和應用服務器的解耦。
優勢:相比session replication的方案,集羣間對於寬帶和內存的壓力減小了不少。
缺點:須要維護存儲session的數據庫。
四、Cookie Base:cookie base就是把session存在cookie中,有瀏覽器來告訴應用服務器個人session是什麼,一樣實現了session和應用服務器的解耦。
優勢:實現簡單,基本免維護。
缺點:cookie長度限制,安全性低,寬帶消耗。
值得一提的是:
nginx目前支持的負載均衡算法有wrr、sh(支持一致性哈希)、fair(本人以爲能夠歸結爲lc)。但nginx做爲均衡器的話,還能夠一同做爲靜態資源服務器。
keepalived+ipvsadm比較強大,目前支持的算法有:rr、wrr、lc、wlc、lblc、sh、dh
keepalived支持集羣模式有:NAT、DR、TUN
nginx自己並無提供session同步的解決方案,而apache則提供了session共享的支持。
好了,解決了以上的問題以後,系統的結構以下:
數據庫作讀庫的話,經常對模糊查找力不從心,即便作了讀寫分離,這個問題還未能解決。以咱們所舉的交易網站爲例,發佈的商品存儲在數據庫中,用戶最常使用的功能就是查找商品,尤爲是根據商品的標題來查找對應的商品。對於這種需求,通常咱們都是經過like功能來實現的,可是這種方式的代價很是大。此時咱們可使用搜索引擎的倒排索引來完成。
搜索引擎並不能替代數據庫,他解決了某些場景下的「讀」的問題,是否引入搜索引擎,須要綜合考慮整個系統的需求。引入搜索引擎後的系統結構以下:
一、後臺應用層和數據庫層的緩存
值得一提的是:
緩存集羣的調度算法不一樣與上面提到的應用服務器和數據庫。最好採用「一致性哈希算法」,這樣才能提升命中率。這個就不展開講了,有興趣的能夠查閱相關資料。
咱們的網站演進到如今,交易、商品、用戶的數據都還在同一個數據庫中。儘管採起了增長緩存,讀寫分離的方式,但隨着數據庫的壓力繼續增長,數據庫的瓶頸愈來愈突出,此時,咱們能夠有數據垂直拆分和水平拆分兩種選擇。
7.一、數據垂直拆分
垂直拆分的意思是把數據庫中不一樣的業務數據拆分道不一樣的數據庫中,結合如今的例子,就是把交易、商品、用戶的數據分開。
垂直拆分後的結構以下:
7.二、數據水平拆分
數據水平拆分就是把同一個表中的數據拆分到兩個甚至多個數據庫中。產生數據水平拆分的緣由是某個業務的數據量或者更新量到達了單個數據庫的瓶頸,這時就能夠把這個表拆分到兩個或更多個數據庫中。
數據水平拆分後的結構:
8.一、拆分應用
隨着業務的發展,業務愈來愈多,應用愈來愈大。咱們須要考慮如何避免讓應用愈來愈臃腫。這就須要把應用拆開,從一個應用變爲倆個甚至更多。仍是以咱們上面的例子,咱們能夠把用戶、商品、交易拆分開。變成「用戶、商品」和「用戶,交易」兩個子系統。
拆分後的結構:
8.二、走服務化的道路
爲了解決上面拆分應用後所出現的問題,咱們把公共的服務拆分出來,造成一種服務化的模式,簡稱SOA。
採用服務化以後的系統結構:
以上的演變過程只是一個例子,並不適合全部的網站,實際中網站演進過程與自身業務和不一樣遇到的問題有密切的關係,沒有固定的模式。只有認真的分析和不斷地探究,才能發現適合本身網站的架構。