天天看點

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

資料庫演化

讀寫分離

即利用大多主流資料庫都具有的“主從熱備”功能,主庫可同步資料到從庫,故,寫資料到主庫,從庫進行讀資料,另外,應使用專門的資料通路子產品進行資料操作,使資料庫的讀寫分離對應用透明

業務分庫

将不同業務的資料庫部署在不同的實體伺服器上

分布式資料庫

資料庫拆分的最後手段,使用多台伺服器進行資料庫叢集,一般在單表資料非常大的情況下才進行

應用系統共有業務抽離

單獨用一個系統負責共有業務,以減少資料庫連接配接數目,然後通過分布式服務調用共有業務

反向代理與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; 
複制代碼
           

分布式消息隊列

定義

在單一伺服器内部可通過多線程共享記憶體隊列的方式實作異步,處在業務操作前面的線程将輸出寫入到隊列,後面的線程從隊列中讀取資料進行處理;在分布式系統中,多個伺服器叢集通過分布式消息隊列實作異步,分布式消息隊列可以看作是記憶體隊列的分布式部署。

作用

  • 提高系統可用性 消費者伺服器發生故障是,資料會在消息隊列伺服器中存儲堆積,生産者伺服器可以繼續處理業務請求,系統整體表現無故障。消費者伺服器恢複正常後,繼續處理消息隊列的資料。
  • 加快網站響應速度 處在業務處理前端的生産者伺服器在處理完業務請求後,将資料寫入消息隊列,不需要等待消費者伺服器處理就可以傳回,相應延遲減少。
  • 消除并發通路高峰 使用者通路網站是随機的,存在通路高峰和低谷,即使網站按照一般通路高峰進行規劃和部署,也依然會出現突發事件,比如購物網站的促銷活動,微網誌上的熱點事件,都會造成網站并發通路突然增大,這可能會造成整個網站負載過重,相應延遲,嚴重時甚至會出現服務當機的情況。使用消息隊列将突然增加的通路請求資料放入消息隊列中,等待消費者伺服器依次處理,就不會對整個網站負載造成太大壓力。

優化網站性能方案

浏覽器端

  • 使用浏覽器緩存
  • 使用頁面壓縮
  • 合理布局頁面
  • 減少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