Web項目開發中用到的緩存技術

在WEB開發中用來應付高流量最有效的辦法就是用緩存技術,能有效的提升服務器負載性能,用空間換取時間。
緩存通常用來php

  • 存儲頻繁訪問的數據
  • 臨時存儲耗時的計算結果
  • 內存緩存減小磁盤IO

使用緩存的2個主要緣由:css

  • 下降延遲:緩存離客戶端更近,所以,從緩存請求內容比從源服務器所用時間更少,呈現速度更快,網站就顯得更靈敏。
  • 下降網絡傳輸:副本被重複使用,大大下降了用戶的帶寬使用,其實也是一種變相的省錢(若是流量要付費的話),同時保證了帶寬請求在一個低水平上,更容易維護了。

 

在WEB開發中,緩存能夠分爲:

 

1、數據庫端緩存

  • 數據庫的緩存通常由數據庫提供,能夠對錶創建高速緩存。數據庫中,用戶可能屢次執行相同的查詢語句,爲了提升查詢效率,數據庫會在內存劃分一個專門的區域,用來存放用戶最近執行的查詢,這塊區域就是緩存。(參考MYSQL緩存)
  • 「空間換時間」,好比建一個表來存儲另一個表某個類型的數據的總條數,在每次更新數據的時候同事更新 數據表和統計條數的表。在須要獲取某個類型的數據的條數的時候,就不須要select count去查詢,直接查詢統計表就能夠了,這樣能夠提升查詢的速度和數據庫的性能。
  • 數據庫查詢緩存,每次訪問頁面的時候,都會先檢測相應的緩存數據是否存在,若是不存在,就鏈接數據庫,獲得數據,並把查詢結果序列化後保存到文件中,之後一樣的查詢結果就直接從緩存表或文件中得到。用的最廣的例子看Discuz的搜索功能,把結果ID緩存到一個表中,下次搜索相同關鍵字時先搜索緩存表。舉個經常使用的方法,多表關聯的時候,把附表中的內容生成數組保存到主表的一個字段中,須要的時候數組分解一下,這樣的好處是隻讀一個表,壞處就是兩個數據同步會多很多步驟,數據庫永遠是瓶頸,用硬盤換速度,是這個的關鍵點。

 

2、應用層緩存

應用層緩存這塊跟開發人員關係最大,也是平時常常接觸的。html

  • 緩存數據庫的查詢結果,減小數據的壓力。這個在大型網站是必須作的。
  • 緩存磁盤文件的數據。好比經常使用的數據能夠放到內存,不用每次都去讀取磁盤,特別是密集計算的程序,好比中文分詞的詞庫。
  • 緩存某個耗時的計算操做,好比數據統計。

應用層緩存的架構也能夠分幾種:前端

  • 嵌入式,也就是緩存和應用在同一個機器。好比單機的文件緩存,java中用hashMap來緩存數據等等。這種緩存速度快,沒有網絡消耗。
  • 分佈式緩存,把緩存的數據獨立到不一樣的機器,經過網絡來請求數據,好比經常使用的memcache就是這一類。

比較常見的應用層分佈式緩存容器,Memcache、共享文件服務器、MemcacheDb、Tokyo Tyrant。 php裏面也有好比x-cache,apc等的基於進程的緩存,這種緩存比分佈式緩存速度快,可是限於跟應用的一個機器。 java實現的緩存也比較多,好比oscache,jcache ,ehcached等等。java

 

3、前端緩存(服務端緩存)

咱們這裏說的前端緩存能夠理解爲通常使用的cdn技術,利用squid等作前端緩衝技術,主要仍是針對靜態文件類型,好比圖片,css,js,html等靜態文件。
通常針對靜態資源如CSS,JS,圖片等使用緩存,緣由以下:node

  • 請求更快:經過將內容緩存在本地瀏覽器或距離最近的緩存服務器(如CDN),在不影響網站交互的前提下能夠大大加快網站加載速度。
  • 節省帶寬:對於已緩存的文件,能夠減小請求帶寬甚至無需請求網絡。
  • 下降服務器壓力:在大量用戶併發請求的狀況下,服務器的性能受到限制,此時將一些靜態資源放置在網絡的多個節點,能夠起到均衡負載的做用,下降服務器的壓力。

前端比較經常使用的就是squid,Varnish Cache,ncache等等。Varnish是一款高性能的開源HTTP加速器,挪威最大的在線報紙 Verdens Gang (vg.no) 使用3臺Varnish代替了原來的12臺squid,性能比之前更好。web

 

4、客戶端緩存(瀏覽器緩存)

客戶端緩存依賴於瀏覽器的實現,目前通常的瀏覽器都實現了基於http都信息來緩存相應的文件。瀏覽器端的緩存,可讓用戶請求一次以後,下一次不在從服務器端請求數據,直接從本地緩存讀取,能夠減輕服務器負擔也能夠加快用戶的訪問速度。
瀏覽器緩存分爲強緩存和協商緩存:數據庫

  • 強緩存:瀏覽器在加載資源時,先根據這個資源的一些http header判斷它是否命中強緩存,強緩存若是命中,瀏覽器直接從本身的緩存中讀取資源,不會發請求到服務器。好比某個css文件,若是瀏覽器在加載它所在的網頁時,這個css文件的緩存配置命中了強緩存,瀏覽器就直接從緩存中加載這個css,連請求都不會發送到網頁所在服務器;
  • 協商緩存:當強緩存沒有命中的時候,瀏覽器必定會發送一個請求到服務器,經過服務器端依據資源的另一些http header驗證這個資源是否命中協商緩存,若是協商緩存命中,服務器會將這個請求返回(304),可是不會返回這個資源的數據,而是告訴客戶端能夠直接從緩存中加載這個資源,因而瀏覽器就又會從本身的緩存中去加載這個資源;若未命中請求,則將資源返回客戶端,並更新本地緩存數據(200)。

強緩存與協商緩存區別:強緩存不發請求到服務器,協商緩存會發請求到服務器。apache

 

如何設置緩存
1. HTML Meta標籤控制緩存(非HTTP協議定義)
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
上述代碼的做用是告訴瀏覽器當前頁面不被緩存,每次訪問都須要去服務器拉取。這種方法使用上很簡單,但只有部分瀏覽器能夠支持,並且全部緩存代理服務器都不支持,由於代理不解析HTML內容自己。segmentfault

2. HTTP頭信息控制緩存

HTTP頭信息發送在HTML代碼以前,只能被瀏覽器和一些中間緩存能看到,一個典型的HTTP 1.1協議返回的頭信息看上去像這樣:

HTTP/1.1 200 OK
Date: Fri, 30 Oct 1998 13:19:41 GMT
Server: Apache/1.3.3 (Unix)
Cache-Control: max-age=3600, must-revalidate
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Last-Modified: Mon, 29 Jun 1998 02:28:12 GMT
ETag: "3e86-410-3596fbbc"
Content-Length: 1040
Content-Type: text/html

頭信息空一行後是HTML代碼的輸出。

HTTP頭信息控制緩存是經過Expires(強緩存)、Cache-control(強緩存)、Last-Modified/If-Modified-Since(協商緩存)、Etag/If-None-Match(協商緩存)實現,下面詳細介紹。
1)Expires是http1.0提出的一個表示資源過時時間的header,它描述的是一個絕對時間,由服務器返回,用GMT格式的字符串表示,如:Expires:Thu, 31 Dec 2016 23:55:55 GMT,讀取緩存數據條件:緩存過時時間(服務器的)< 當前時間(客戶端的)。
儘管Expires頭頗有用,但它有必定的侷限性。首先,由於牽扯到時間,Web服務器端的時鐘必須和緩存的同步,不然極可能實現不了預期的結果——緩存把前女朋友當初現女朋友,把現女朋友看成過去式——那就悲劇了。另一個問題是,你很容易忘記給某內容設置了一個特定時間,若是返回內容的時候沒有更新這個過時時間,則每一個請求都是上訪到服務器,反而增長了負載和響應時間。
缺點:Expires是較老的強緩存管理header,因爲它是服務器返回的一個絕對時間,這樣存在一個問題,若是客戶端的時間與服務器的時間相差很大(好比時鐘不一樣步,或者跨時區),那麼偏差就很大,因此在HTTP 1.1版開始,使用Cache-Control: max-age=秒替代。
2)Cache-Control(緩存控制)HTTP頭信息,是HTTP 1.1引入了新的頭信息,描述的是一個相對時間,在進行緩存命中的時候,都是利用客戶端時間進行判斷,因此相比較Expires,Cache-Control的緩存管理更有效,安全一些。讀取緩存數據條件:上次緩存時間(客戶端的)+max-age < 當前時間(客戶端的)。Cache-Control值能夠是public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age

各個消息中的指令含義以下:

  • max-age=[秒]:表示在這個時間範圍內緩存是新鮮的無需更新。相似Expires時間,不過這個時間是相對的,而不是絕對的。也就是某次請求成功後多少秒內緩存是新鮮的。(指示客戶機能夠接收生存期不大於指定時間(以秒爲單位)的響應。上次緩存時間(客戶端的)+max-age(64200s)<客戶端當前時間)
  • s-maxage=[秒]:相似max-age, 除了僅應用於共享緩存(如代理)。
  • min-fresh指示客戶機能夠接收響應時間小於當前時間加上指定時間的響應。
  • max-stale指示客戶機能夠接收超出超時期間的響應消息。若是指定max-stale消息的值,那麼客戶機能夠接收超出超時期指定值以內的響應消息。
  • public:指示響應可被任何緩存區緩存。通常而言,須要認證HTTP請求內容會自動私有化(不會被緩存Add)。
  • private:指示對於單個用戶的整個或部分響應消息,不能被共享緩存處理。這容許服務器僅僅描述當前用戶的部分響應消息,此響應消息對於其餘用戶的請求無效。(容許緩存專門爲某一個用戶存儲響應,比方說在瀏覽器中;共享緩存通常不會,例如在代理中。)
  • no-cache:指示請求或響應消息不能緩存,該選項並非說能夠設置」不緩存「,而是須要和服務器確認。(每次在釋放緩存副本以前都強制發送請求給源服務器進行驗證,這在確保認證有效性上很管用(和public結合使用)或者保證內容必須是即時的,不得無視緩存的全部優勢,如國內的微博、twitter等的刷新顯示Add。)
  • no-store:在請求消息中發送將使得請求和響應消息都不使用緩存,徹底不存下來。(強制緩存在任何狀況下都不要保留任何副本。)
  • must-revalidate:告訴緩存,我給你準備了一些關於新鮮度的信息,在表現的時候要嚴格遵循之。HTTP容許緩存在某些特定狀況下返回過時數據,指定了這個屬性,相對於告訴緩存,你丫必須嚴格遵循個人規則。
  • proxy-revalidate:相似must-revalidate,除了只能應用於代理緩存。

注意:這兩個header能夠只啓用一個,也能夠同時啓用,當response header中,Expires和Cache-Control同時存在時,Cache-Control優先級高於Expires。

3)Last-Modified/If-Modified-Since:Last-Modified/If-Modified-Since要配合Cache-Control使用。
Last-Modified:標示這個響應資源的最後修改時間。web服務器在響應請求時,告訴瀏覽器資源的最後修改時間。
If-Modified-Since:當資源過時時(強緩存失效),發現資源具備Last-Modified聲明,則再次向web服務器請求時帶上頭 If-Modified-Since,表示請求時間。web服務器收到請求後發現有頭If-Modified-Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。
缺點:Last-Modified標註的最後修改只能精確到秒級,若是某些文件在1秒鐘之內,被修改屢次的話,它將不能準確標註文件的修改時間(沒法及時更新文件)
若是某些文件會被按期生成,當有時內容並無任何變化,但Last-Modified卻改變了,致使文件無法使用緩存,有可能存在服務器沒有準確獲取文件修改時間,或者與代理服務器時間不一致等情形(沒法使用緩存)。
HTTP1.1中Etag解決了上述問題。
4)Etag/If-None-Match:Etag/If-None-Match也要配合Cache-Control使用。
Etag:web服務器響應請求時,告訴瀏覽器當前資源在服務器的惟一標識(生成規則由服務器決定)。Apache中,ETag的值,默認是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後獲得的。
If-None-Match:當資源過時時(使用Cache-Control標識的max-age),發現資源具備Etage聲明,則再次向web服務器請求時帶上頭If-None-Match (Etag的值)。web服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304。
Etag是服務器自動生成或者由開發者生成的對應資源在服務器端的惟一標識符,可以更加準確的控制緩存。Last-Modified與ETag一塊兒使用時,服務器會優先驗證ETag。
yahoo的Yslow法則中則提示謹慎設置Etag:須要注意的是分佈式系統裏多臺機器間文件的last-modified必須保持一致,以避免負載均衡到不一樣機器致使比對失敗,Yahoo建議分佈式系統儘可能關閉掉Etag(每臺機器生成的etag都會不同,由於除了 last-modified、inode 也很難保持一致)。

 

緩存的更新和過時

咱們這幾隻講應用層的緩存。在應用層的緩存因爲應經有新的數據加入,數據的修改,數據的刪除等等操做,而在某些時間,咱們須要這些操做及時的生效(因爲用了緩存,可能會致使修改後緩存沒有更新,而頁面也沒有變化),因此出現緩存的更新和過時的概念。

緩存的過時包含

  • 時間過時:咱們在緩存數據的時候咱們能夠指定數據緩存的最大時間,若是超過這個時間,咱們就認爲緩存是失效的。
  • 基於規則的過時:咱們在緩存中存儲了某些數據來標明數據的版本。好比存取的時間,更新的時間,數據的版本信息等等,而後比較這些信息是否有變化來判斷是否過時。

緩存的更新

  • 被動:當緩存失效的時候咱們的應用程序從新從主存儲器中取數據,而後從新放回緩存中。
  • 主動:當數據一更新的時候,咱們的應用主動的去更新咱們的緩存內容。
  • 被動和主動結合(基於版本):當數據以更新的時候,咱們更新一個數據被更新的標誌。而後根據上面講到的「基於規則的過時」來更新數據。

 

如何評價緩存的好壞

速度:固然,咱們使用緩存的目的之一就是要提升咱們應用的速度。若是使用緩存後速度更慢那就沒有緩存的必要了。取緩存的速度應 當是很是快的,由於緩存的工做僅僅是取出一個曾經存儲好的數據。因此影響緩存速度的因素可能跟緩存所才採用的存儲方式有關係,還有可能印象速度的就是分佈 式緩存的網絡消耗,一樣,緩存服務器在併發很大的時候也有可能不堪重負出現瓶頸,變得緩慢。
好比目前鳳凰論壇使用的帖子緩存的響應時間在亞毫秒級,也就是還不足1ms的響應時間,這個速度是至關快的。
及時性:咱們使用緩存的重要一點就是對咱們的數據的更新須要緩存也及時的更新。這點很是重要,關係到頁面顯示的正確性,用戶體驗等。
命中率:命中率直接關係到緩存所起到的做用的大小。若是命中率過低就至關於沒有使用緩存,或者咱們的緩存的規則有問題,重視命中不到緩存。


如何有效的使用緩存

哪些地方須要緩存

  • 頁面的打開速度很是慢,每一次都要進行大量的計算,從數據庫取一個比較耗時操做的數據。
  • 頻繁的讀取操做,每次請求都要從數據庫讀取數據,而這些數據的更新並非很頻繁,致使數據庫的壓力很是大。
  • 頻繁的寫入操做(須要寫到數據庫),好比頁面點擊量,投票數的操做。這些操做能夠暫時利用緩存,而後按期的寫到數據庫。

選擇什麼緩存
緩存如此有用,那麼這麼多的緩存產品,咱們如何選擇呢?下面咱們主要就經常使用的php方面來講。

  • 訪問量不是特別大,web前端機器只有一臺,對數據庫端的內容緩存可使用文件緩存,這種方式很是簡單也比較有效,不須要對服務器作特別的配置。也可使用apc,x-cached等提供的內存緩存,也很是有效,它比磁盤緩存速度快,可是由於是內存緩存,因此緩存的容量有限。
  • 訪問量比較大,web前端機器通常超過一臺甚至更多,咱們通常採用分佈式的緩存。咱們通常選擇memcache做爲咱們的緩存,memcache是一個基於內存的分佈式緩存,它的速度和效率很是高。

其實這裏也可使用共享的磁盤緩存,可是基於咱們目前所處的環境和對於可靠性,高併發的要求,咱們不建議或者說不考慮使用共享磁盤做爲緩存。

 


================PHP中9大緩存技術總結===================

一、全頁面靜態化緩存
也就是將頁面所有生成html靜態頁面,用戶訪問時直接訪問的靜態頁面,而不會去走php服務器解析的流程。此種方式,在CMS系統中比較常見,好比dedecms;

二、頁面部分緩存
該種方式,是將一個頁面中不常常變的部分進行靜態緩存,而常常變化的塊不緩存,最後組裝在一塊兒顯示;可使用相似於ob_get_contents的方式實現,也能夠利用相似ESI之類的頁面片斷緩存策略,使其用來作動態頁面中相對靜態的片斷部分的緩存(ESI技術,請baidu,此處不詳講)。該種方式能夠用於如商城中的商品頁。

三、數據緩存
顧名思義,就是緩存數據的一種方式;好比,商城中的某個商品信息,當用商品id去請求時,就會得出包括店鋪信息、商品信息等數據,此時就能夠將這些數據緩存到一個php文件中,文件名包含商品id來建一個惟一標示;下一次有人想查看這個商品時,首先就直接調這個文件裏面的信息,而不用再去數據庫查詢;其實緩存文件中緩存的就是一個php數組之類。Ecmall商城系統裏面就用了這種方式。

四、查詢緩存
其實這跟數據緩存是一個思路,就是根據查詢語句來緩存;將查詢獲得的數據緩存在一個文件中,下次遇到相同的查詢時,就直接先從這個文件裏面調數據,不會再去查數據庫;但此處的緩存文件名可能就須要以查詢語句爲基點來創建惟一標示;
按時間變動進行緩存:其實,這一條不是真正的緩存方式;上面的二、三、4的緩存技術通常都用到了時間變動判斷;就是對於緩存文件您須要設一個有效時間,在這個有效時間內,相同的訪問纔會先取緩存文件的內容,可是超過設定的緩存時間,就須要從新從數據庫中獲取數據,並生產最新的緩存文件;好比,我將咱們商城的首頁就是設置2個小時更新一次。

五、按內容變動進行緩存
這個也並不是獨立的緩存技術,需結合着用;就是當數據庫內容被修改時,即刻更新緩存文件。好比,一我的流量很大的商城,商品不少,商品表必然比較大,這表的壓力也比較重;咱們就能夠對商品顯示頁進行頁面緩存;當商家在後臺修改這個商品的信息時,點擊保存,咱們同時就更新緩存文件;那麼,買家訪問這個商品信息時,實際上訪問的是一個靜態頁面,而不須要再去訪問數據庫。
試想,若是對商品頁不緩存,那麼每次訪問一個商品就要去數據庫查一次,若是有10萬人在線瀏覽商品,那服務器壓力就大了;

六、內存式緩存
提到這個,可能你們想到的首先就是Memcached;memcached是高性能的分佈式內存緩存服務器。 通常的使用目的是,經過緩存數據庫查詢結果,減小數據庫訪問次數,以提升動態Web應用的速度、 提升可擴展性。它就是將須要緩存的信息,緩存到系統內存中,須要獲取信息時,直接到內存中取;比較經常使用的方式就是 key–>value方式。

七、apache緩存模塊
apache安裝完之後,是不容許被cache的。若是外接了cache或squid服務器要求進行web加速的話,就須要在htttpd.conf裏進行設置,固然前提是在安裝apache的時候要激活mod_cache的模塊。
安裝apache時:./configure –enable-cache –enable-disk-cache –enable-mem-cache

八、php APC緩存擴展
Php有一個APC緩存擴展,windows下面爲php_apc.dll,須要先加載這個模塊,而後是在php.ini裏面進行配置:

[apc] 
extension=php_apc.dll 
apc.rfc1867 = on 
upload_max_filesize = 100M 
post_max_size = 100M 
apc.max_file_size = 200M 
upload_max_filesize = 1000M 
post_max_size = 1000M 
max_execution_time = 600 ; 每一個PHP頁面運行的最大時間值(秒),默認30秒 
max_input_time = 600 ; 每一個PHP頁面接收數據所需的最大時間,默認60 
memory_limit = 128M ; 每一個PHP頁面所吃掉的最大內存,默認8M

 

九、Opcode緩存
PHP的緩衝器、加速器,有eaccelerator, apc, phpa,xcache。
首先php代碼被解析爲Tokens,而後再編譯爲Opcode碼,最後執行Opcode碼,返回結果;因此,對於相同的php文件,第一次運行時能夠緩存其Opcode碼,下次再執行這個頁面時,直接會去找到緩存下的opcode碼,直接執行最後一步,而再也不須要中間的步驟了。比較知名的是XCache、Turck MM Cache、PHP Accelerator等。



文章參考:

http://www.cnblogs.com/sunli/archive/2009/11/24/1609444.html
https://segmentfault.com/a/1190000006741200
https://my.oschina.net/leejun2005/blog/369148
http://www.oschina.net/news/41397/web-cache-knowledge
http://www.open-open.com/lib/view/open1479181086120.html
http://www.jb51.net/article/49714.htm
http://www.php100.com/html/php/lei/2015/0919/8969.html

 

版權聲明:本文采用署名-非商業性使用-相同方式共享(CC BY-NC-SA 3.0 CN)國際許可協議進行許可,轉載請註明做者及出處。
本文標題:Web項目開發中用到的緩存技術
本文連接:http://www.cnblogs.com/sochishun/p/7326752.html
本文做者:SoChishun (郵箱:14507247#qq.com | 博客:http://www.cnblogs.com/sochishun/)發表日期:2017年8月9日

相關文章
相關標籤/搜索