《大型網站技術架構:核心原理與案例分析》之讀書筆記

數據庫演化

讀寫分離

即利用大多主流數據庫都具備的「主從熱備」功能,主庫可同步數據到從庫,故,寫數據到主庫,從庫進行讀數據,另外,應使用專門的數據訪問模塊進行數據操做,使數據庫的讀寫分離對應用透明html

業務分庫

將不一樣業務的數據庫部署在不一樣的物理服務器上前端

分佈式數據庫

數據庫拆分的最後手段,使用多臺服務器進行數據庫集羣,通常在單表數據很是大的狀況下才進行nginx

應用系統共有業務抽離

單獨用一個系統負責共有業務,以減小數據庫鏈接數目,而後經過分佈式服務調用共有業務web

反向代理與nginx

nginx支持負載均衡和反向代理:算法

  • 例如tomcat進行集羣,可以使用server節點配置多tomcat訪問的負載均衡,如:
upstream tomcatserver {
        server 192.168.72.49:8082;
        server 192.168.72.49:8081;
    }
    server {
        listen       80;
        server_name  localhost;
        main;
        location / {
            proxy_pass   http://tomcatserver;
            index  index.html index.htm;
        }     
    }
複製代碼
  • 反向代理通常用於加速網站響應(除此以外,還可以使用CDN進行加速),即當用戶訪問網站服務時,若是nginx緩存有用戶請求的資源,則將其直接返回給用戶。 要想開啓nginx的緩存功能,須要添加此處的兩行內容:
#這一行分別表示:定義緩存存儲目錄,手動建立;緩存級別,表示緩存目錄的第一級目錄是1個字符,第二級目錄是2個字符;內核中創建用於緩存緩存數據源數據的空間,查找緩存的時候,先從這個內核空間中找到,緩存數據的源數據,而後再到對應目錄中查找緩存;這一行分別表示:緩存空間最大值;緩存的數據,60分鐘內沒有被訪問過就刪除 
proxy_cache_path /var/www/cache levels=1:2 keys_zone=mycache:20m max_size=2048m inactive=60m;
#這一行分別表示:建立緩存的時候可能生成一些臨時文件存放的位置,自動建立 
proxy_temp_path /var/www/cache/tmp; 
複製代碼

分佈式消息隊列

定義

在單一服務器內部可經過多線程共享內存隊列的方式實現異步,處在業務操做前面的線程將輸出寫入到隊列,後面的線程從隊列中讀取數據進行處理;在分佈式系統中,多個服務器集羣經過分佈式消息隊列實現異步,分佈式消息隊列能夠看做是內存隊列的分佈式部署。數據庫

做用

  • 提升系統可用性 消費者服務器發生故障是,數據會在消息隊列服務器中存儲堆積,生產者服務器能夠繼續處理業務請求,系統總體表現無端障。消費者服務器恢復正常後,繼續處理消息隊列的數據。apache

  • 加快網站響應速度 處在業務處理前端的生產者服務器在處理完業務請求後,將數據寫入消息隊列,不須要等待消費者服務器處理就能夠返回,相應延遲減小。後端

  • 消除併發訪問高峯 用戶訪問網站是隨機的,存在訪問高峯和低谷,即便網站按照通常訪問高峯進行規劃和部署,也依然會出現突發事件,好比購物網站的促銷活動,微博上的熱點事件,都會形成網站併發訪問忽然增大,這可能會形成整個網站負載太重,相應延遲,嚴重時甚至會出現服務宕機的狀況。使用消息隊列將忽然增長的訪問請求數據放入消息隊列中,等待消費者服務器依次處理,就不會對整個網站負載形成太大壓力。瀏覽器

優化網站性能方案

瀏覽器端

  • 使用瀏覽器緩存
  • 使用頁面壓縮
  • 合理佈局頁面
  • 減小cookie傳輸

動靜分離

  • 使用CDN將靜態內容分發到離用戶最近的網絡服務商機房
  • 在中心機房部署反向代理服務器,緩存熱點文件

應用服務器端

  • 使用分佈式緩存
  • 使用本地緩存

其餘

  • 異步:使用消息隊列支持異步操做,即將用戶請求發送到消息隊列等待後續任務處理,而當前請求直接響應給用戶
  • 集羣:對於高併發請求,將多臺應用服務器組成集羣共同對外訪問注意集羣下,儘可能不將重要的會話數據保存在當前服務器中,而是分佈式緩存等地方,爲了防止發生宕機,會話數據丟失

代碼層面

  • 使用多線程
  • 改善內存管理

數據庫服務器端

  • 數據庫:索引、緩存、SQL優化等
  • NOSQL優化數據模型、存儲結構、伸縮特性等

可用性

即通常的7*24小時可用,主流網站通常知足4個9以上可用性(即99.99%),即叫作高可用;2個9是基本可用;3個9爲較高可用;5個9爲極高可用。實現高可用的主要手段便是冗餘:服務器集羣,數據熱備,主從替換緩存

伸縮性

大型網站須要面對大量的用戶的高併發訪問和存儲海量數據,不可能只用一臺服務器就處理所有用戶請求,存儲所有數據,故出現了集羣。而所謂伸縮性即經過不斷向集羣中加入服務器的手段來緩解不斷上升的用戶併發訪問壓力和不斷增加的數據存儲需求。

衡量伸縮性的主要標準便是是否能夠用多臺服務器構建集羣,是否容易向集羣中間添加新的服務器。加入新的服務器是否能夠提供和原來的服務器無差異的服務,集羣中可容納的總服務器數量是否有限制。

實現伸縮性:

  • 對於應用服務器集羣:不在服務器上保存數據(本地緩存),那麼所用服務器都是對等的,即具備良好伸縮性。
  • 對於緩存服務器集羣:加入新的服務器可能致使緩存路由失效,進而致使集羣中的大部分緩存數據沒法訪問。可經過改進路由算法保證緩存數據的可訪問性,即採用一致性hash算法,繼續升級:將物理節點分解成多個虛擬節點來進行新增節點操做以保證較均勻地影響原來集羣中的服務器。
  • 對於數據庫集羣:關係型數據庫雖支持數據複製,朱從熱備,但很難作到可伸縮性,所以只能從數據庫外部來實現,經過路由分區等方法將部署多個數據庫的服務器組成一個集羣。

擴展性

衡量擴展性的主要標準便是網站增長新的業務產品時,是否能夠實現對現有產品透明無影響,不一樣產品之間耦合度不多,一個產品的改動對另外一個產品無影響。

實現擴展性:

  • 事件驅動架構:在網站一般利用消息隊列實現,將用戶請求和其餘業務事件構形成消息發佈到消息隊列中,消息的處理者做爲消費者從消費隊列中獲取消息進行處理。經過這種方式將消息產生和消息處理分離開來,能夠透明地增長新的消息生產者任務或者新的消息消費者任務。
  • 分佈式服務:即將業務和可複用服務分離開來,經過分佈式服務框架調用。新增產品能夠經過調用可複用的服務實現自身的業務邏輯,而對現有的產品沒有任何影響。可複用服務升級變動的時候,也能夠經過提供多版本服務對應用實現透明升級,不須要強制應用同步變動。

網站優化手段

前端

  • 優化頁面html式樣
  • 利用瀏覽器的併發和異步特性
  • 減小http請求
  • 啓用壓縮,HTML、CSS、Javascript文件啓用GZip壓縮
  • Css放頁面最上面,Javascript放最下面
  • 減小Cookie傳輸
  • 瀏覽器緩存策略
  • 使用CDN、反向代理

後端

緩存

  1. 頻繁修改的數據:讀寫比在2:1以上,緩存纔有意義,即一次寫入,再次寫入前應至少讀取兩次
  2. 沒有熱點的訪問:若是訪問數據不遵循二八定律,緩存沒有意義
  3. 數據不一致與髒讀:兩種策略,一是設置過時時間,合理過時;二是當即更新緩存
  4. 緩存可用性:緩存宕機,對數據庫形成衝擊,須要注意。對此,有緩存熱備和分佈式緩存,前者宕機切換到另外一臺緩存服務器不推薦,後者創建集羣
  5. 緩存預熱:新啓動的緩存系統若是沒有熱點數據,應在啓動時就將熱點數據加載好,這種預加載手段即緩存預熱
  6. 緩存穿透:對前端高併發請求不存在的數據,也應自動加到緩存中(其值能夠是null),防止對數據庫形成壓力。
  7. 常見架構:一是以jboss cache爲表明的更新同步緩存,每臺應用服務器本機都對應有一個jboss cache,各個jboss cache相互更新同步數據;而是以memcached爲表明的互不通信緩存,集羣下的mencached共同組成一個大緩存。

集羣

使用負載均衡進行集羣

異步操做

即便用消息隊列,前端的請求發送到應用服務器,服務器再發送到消息隊列服務器進行一一處理,形象說就是前端用戶排隊作的事情(即存在等待),所有交給後端來進行排隊,而後前端即時返回消息。

代碼優化

  1. 使用多線程
  1. 緣由:等待IO操做時,cpu能夠作其餘事;多cpu狀況下,想要最大限度使用cpu,必須啓動多線程
  2. 啓動線程數=[任務執行時間/(任務執行時間-IO等待時間)]xCPU內核數 故使用場景在於IO耗時長、CPU內核多的狀況
  3. 解決線程安全:將對象設計成無狀態對象、使用局部對象(方法內部對象)、併發訪問時使用鎖
  1. 資源複用

減小開銷很大的資源建立和銷燬,如:數據庫鏈接、網絡通訊鏈接、線程、複雜對象,故,經常使用兩種方式:單例和對象池,具體如:Service到Dao的單例、鏈接池、線程池

  1. 數據結構
  2. 垃圾回收

Young Generation(Eden+From+To)+Old Geneartion Eden區建立對象,區滿則觸發Young GC,Eden區中仍在被使用的對象複製到From區,再次區滿,Eden區+From區仍在被使用的對象複製到To區,再次區滿,則Eden區和To區仍在被使用對象複製到From區,以此類推。當超過某個閾值對象還未被釋放,將複製到Old Generation。若是Old Generation區滿,進行Full GC(全量回收,影響性能),應儘可能減小Full GC

存儲性能優化

  • 機械硬盤 vs 固態硬盤 機械硬盤對於隨機訪問時,移動磁頭臂次數不少,性能不強;固態硬盤(SSD或Flash硬盤)使用可持久記憶的硅晶體存儲,可像內存同樣快速隨機訪問,故SSD性能更佳

  • B+樹 vs LSM數 爲保證數據在不斷更新、插入、刪除後依然有序,傳統關係數據庫使用B+樹,目前許多NoSQL產品使用LSM樹,LSM樹性能更佳,可讓關係數據庫使用LSM數

Session管理

  1. Session複製 應用服務器開啓web容器的Session複製功能,每臺服務器同步session數據,大規模下佔用服務器和網絡大量資源,故適用於小規模集羣

  2. Session綁定 負載均衡服務器老是將同一IP的請求分發給同一臺服務器,如nginx負載均衡的ip_hash策略。若是用戶IP變化將可能失去Session,故可以使用cookie標識以取代IP(此時負載均衡服務器應工做於http協議層)。可是若是服務器宕機,該機存儲的session也仍是會消失,故高可用要求下,不推薦

  3. cookie保存session 每次請求時,cookie攜帶session進行請求,缺點:一是cookie大小可能受限制,二是攜帶session影響性能,三是用戶可能關閉cookie。故也不推薦

  4. session服務器推薦 按照需求劃分兩種:一是基於分佈式緩存或數據庫進行包裝,使其知足session存儲和訪問要求,二是開發專門的session服務平臺,用於單點登陸等。

負載均衡實現方式

  1. HTTP重定向實現負載均衡 用戶請求到達http重定向服務器(負載均衡器),該服務器計算獲得須要訪問的真實目標服務器,並經過302狀態碼返回給用戶進行重定向。缺點是客戶端須要兩次請求才能完成操做,性能較差,且302重定向可能致使搜索引擎斷定爲SEO做弊,下降搜索排名。

  2. DNS域名解析實現負載均衡 在DNS配置中(如阿里控制檯),同一域名配置多個A記錄(A記錄即不一樣目標服務器IP),每次域名解析都會根據負載均衡算法計算一個不一樣的真實目標IP地址返回給客戶端。缺點在於修改A記錄(若有服務器下線時),因爲緩存緣由,生效時間較長(幾分鐘),而且DSN控制權在域名服務商那裏,沒法進行更好的改善和管理。

  3. 反向代理實現負載均衡 反向代理多用於進行網站動靜分離,對一些靜態資源進行反向代理,而無需再訪問web服務器進行拿取,提升響應速度。而反向代理也可用作實現負載均衡,即把「動」的東西進行反向代理。 如apache、nginx等反向代理服務器都提供負載均衡功能:管理一組web服務器,將請求根據負載均衡算法轉發到不一樣的web服務器上。缺點是全部請求和響應都要通過反向代理服務器,性能成爲瓶頸(應用層負載均衡)

  4. IP實現負載均衡 核心即操做數據包,修改目標IP地址,甚至源地址。請求到達負載均衡服務器時,修改請求數據包的目標IP爲經過計算獲得的真實目標服務器。另外,將源地址由客戶端ip修改成負載均衡服務器IP,這樣數據響應將回到負載均衡服務器,繼而返回給客戶端(或者讓負載均衡服務器做爲真實目標服務器集羣的網關服務器,這樣全部響應數據也都會到達負載均衡服務器)

  5. 數據鏈路層實現負載均衡 相似IP實現負載均衡,不過此處是在分發過程當中不修改IP地址,而是mac地址,不過此處須要配置真實目標服務器集羣的全部機器虛擬IP和負載均衡服務器IP一致,這樣不須要再經過負載均衡服務器進行地址轉換,即可將響應數據直接由真實目標服務器返回給客戶端,造成一個三角傳輸模式,這樣,數據響應不通過負載均衡服務器,網絡帶寬也就將不成爲瓶頸。這也是目前大型網站使用最廣的一種負載均衡手段,開源產品有:LVS

相關文章
相關標籤/搜索