1. 程式人生 > >大型網站系統學習筆記

大型網站系統學習筆記

大型網站及其架構演進過程     (一)網站初建
    作為一個交易網站,需要具備的最基本三個功能:     (1) 使用者:使用者註冊、使用者管理、資訊維護……     (2) 商品:商品展示、商品管理……     (3) 交易:建立交易、交易管理……  如果基於JAVA用單機技術,即一臺伺服器來構建應用,示意圖大概會如下所示

各個功能模組之間通過JVM內部方法呼叫來進行互動,而應用和伺服器則通過JDBC進行訪問
(二)單機負載告警,資料庫與應用分離     網站對外服務後,訪問量會不斷增大,對伺服器的負載持續升高,首先我們考慮從結構上進行優化:把資料庫與應用從一臺機器分到兩臺
    
與之前的差別,我們只需把應用的配置中資料庫的訪問地址從一個地址遷移到另一個地址進行,對開發、部署、測試影響不大。     調整能夠緩解當前系統的壓力,但隨著訪問量繼續增大,我們的系統還需繼續演進
(三)應用伺服器負載告警,讓應用伺服器走向叢集 應用伺服器壓力增大,我們把應用從單機變為叢集的方式來進行優化

如上圖所示,應用伺服器從一臺變為兩臺,而它們之間沒有直接互動,都是依賴與資料庫對外提供服務,但我們有兩個問題亟待解決:     (1)使用者對兩個應用伺服器訪問的選擇問題:
  • 通過DNS解決:是在DNS伺服器中為同一個主機名配置多個IP地址,在應答DNS查詢時,DNS伺服器對每個查詢將以DNS檔案中主機記錄的IP地址按順序返回不同的解析結果,將客戶端的訪問引導到不同的機器上去,使得不同的客戶端訪問不同的伺服器。但它的缺點很明顯:
        ① 不能夠按照Web伺服器的處理能力分配負載。DNS負載均衡採用的是簡單的輪循負載演算法,不能區分伺服器之間的差異,不能反映伺服器的當前運行狀態。所以 DNS伺服器將Http請求平均地分配到後臺的Web伺服器上,而不考慮每個Web伺服器當前的負載情況。如果後臺的Web伺服器的配置和處理能力不同, 最慢的 Web伺服器將成為系統的瓶頸,處理能力強的伺服器不能充分發揮作用。
        ② 不支援高可靠性,DNS負載均衡技術沒有考慮容錯。如果後臺的某臺Web伺服器出現故障,DNS伺服器仍然會把DNS 請求分配到這臺故障伺服器上,導致不能響應客戶端。
  • 通過負載均衡硬體裝置來解決
  • 通過nginx等WebSever實現負載均衡如:
  • upstream myServer {   

        server 127.0.0.1:9090 down;
        server 127.0.0.1:8080 weight=2;
        server 127.0.0.1:6060;
        server 127.0.0.1:7070 backup;
    }

    (2) 解決應用伺服器變為集群后的Session問題:Session通過遊覽器與伺服器會話產生,它往往是儲存在單機上的。


    而對於上圖,如果使用者第一次訪問網站,請求落到了左邊的伺服器,那麼Session就建立在左邊的伺服器上,如果不做處理,就不能儲存使用者請求每次都落在存有其session會話資訊的同一伺服器上。針對此問題,我們來看看幾種解決方案:
        1. Session Sticky(滯粘會話)
        當Web伺服器變成多臺時,儲存同一個會話請求在同一伺服器上處理,要做到這一點,需要負載均衡器能夠根據每次請求的會話標識來進行請求轉發    
        如使用nginx的ip_hash,此時nginx必須為最前端伺服器,否則nginx得不到正確的ip,也不能根據ip做hash;同時nginx後端也不能有其它方式的負載均衡,否則請求又會被再次分流,客戶端的請求就很難定位到同一Session應用伺服器上了 upstream backend { server 127.0.0.1:8080; server 127.0.0.1:9090; ip_hash;}         針對nginx此點,我們可以使用pstream_hash這個第三方模組,假如前端是squid,他會將ip加入x_forwarded_for這個http_header裡,用upstream_hash可以用這個頭做因子,將請求定向到指定的後端。再通過 hash   $http_x_forwarded_for; 這樣就改成了利用x_forwarded_for這個頭作因子,在nginx新版本中可支援讀取cookie值,所以也可以改成:

hash   $cookie_jsessionid;

        使用Session Sticky有如下幾個問題:
        ① 如果有一臺伺服器宕機或者重啟,那麼這臺機器上的會話資料會丟失。         ②負載均衡器變為一個有狀態的節點,要將會話儲存到具體Web伺服器的對映,記憶體消耗會更大,容災方面會更麻煩         2. Session Replication         如果把Session Styicky 比喻成我們將碗筷(會話資料)放在特定飯店(伺服器),然後每次吃飯都去那家飯店,那Session Replication可以比喻成在每個飯店裡都存放一套餐具,這樣就可以自己根據每家飯店的擁擠情況自由選擇飯店了。         而我們要做的就是在每次任一伺服器產生會話資料時,將資料複製到其他伺服器中。但這樣會引發一些問題:         ① 同步Session資料造成了網路頻寬的額外開銷,只要Session資料有變化,就需要將資料同步到所有其他機器中,機器數越多,同步帶來的頻寬開銷就越大     ②  如果整個叢集的Session數很多的話(很多人同時訪問網站)每臺機器用於儲存Session資料的內容佔用會很嚴重         3. Session資料集中儲存         將Session資料集中儲存起來,然後不同web伺服器從同一地方獲取Session,而儲存session的具體方式,可以使用資料庫、NOSQL技術或其他分散式儲存系統。它的問題有:         ① 讀寫Session資料引發網路操作,這相對於本機資料讀取來說,就存在時延和不穩定性。         ② 如果集中儲存Session的機器或者叢集出現問題,就會影響我們的應用         4. cookie based         將Session資訊存放到Cookie中,這樣不會依賴與外部系統,也沒有寫入Session資料的網路時延和不穩定性。但Cookie的長度有限制,這樣也會限制了Session的長度,同時可能存在被盜取的安全性問題  (四)資料讀壓力大,採用讀寫分離
        主庫負責讀寫,從庫只提供讀服務。
     
讀寫分離主要帶來的是資料複製問題,對於資料複製的實現,不同資料庫都有相應的內建實現,如mysql的Master-Slave配置,我們主要考慮的是時延問題,如果使用者修改了資訊,但使用者即時檢視時,獲取到的是從庫中尚未更新的資料,就會讓使用者覺得自己沒有修改成功。     (五)讀寫分離後再遇瓶頸,資料庫垂直拆分
   專庫專用,資料垂直拆分,把資料庫與應用從一臺機器分到兩臺,如下圖所示


但垂直拆分可能存在如下問題:
①需配置多個數據源
②分散式事務效能降低
③多表連線查詢等操作變得困難

(六)垂直拆分後再遇瓶頸,單表資料水平拆分


但水平拆分可能存在問題:
①sql查詢路由問題
②主鍵不能重複的保證機制
③分頁排序等獲取問題