一談緩存,心裏頓時豁然開朗。迫於key-value的形式,總感受輕風扶面,楊柳依依,一切都盡在我掌握之中。猶如那一眼相中佳人的衝動,腦子裏滿是佳人的容顏。
那緩存若是站在網站架構的角度,你知道它的設計原理和影響做用嗎?php
在商業的世界裏,常說的一句話是 <span style="color:#773098;font-weight:bold;">"現金爲王"。在互聯網、移動互聯網乃至整個軟件技術的世界裏面,與之相近的就是 <span style="color:#773098;font-weight:bold;">"緩存爲王"。html
爲什麼這麼說呢?
試想一下,你個完整的網絡請求(HTTP、SOAP、RPC等),若是在執行過程的某個部分尚有緩存,是否是就能提早響應給客戶端呢? webpack
爲什麼如今不少中大型公司在面試時,對緩存的應用、原理、高可用等一系列問題,都一撲啦的扔給你,讓你難以招架。緣由都在這。ios
緩存:存儲在計算機上的一個原始數據複製,以便於訪問
--維基百科
緩存是系統快速響應中的一種關鍵技術,是一組被保存起來以備未來使用的東西。介於應用開發和系統開發之間,是產品經理常常估計不到的地方,也是技術架構設計中的非功能性約束。nginx
應用開發我知道,這系統緩存是個什麼狀況呀,小吒哥?
不要着急,日後面看
顧名思義,由多個維度共同組成的緩存工程。由於緩存在不一樣的場景有着不一樣的意義。採用的技術手段也不一樣。 web
按緩存存在形式分:面試
系統緩存是什麼?
操做系統是管理計算機硬件與軟件資源的計算機程序,而硬、軟件件運行速度的快慢基本由緩存決定,緩存的容量越大,相應的硬件運行速度也就越快。因此係統緩存就是操做系統調用硬件資源(內存、文件等)和調用應用程序時,可以啓動加速執行的做用。ajax
總結:操做系統存調用涉及到有緩存的部分,均可算系統緩存
軟件運行都需創建在操做系統之上,在運行時須要把程序裝載到內存中,<span style="color:#773098;font-weight:bold;">但軟件執行操做內存時都是基於虛擬內存映射的機制,並非直接操做物理內存。虛擬內存以塊表(內存塊組成的表格)的形式來存儲相關資源。算法
注:物理內存組成上由多個方塊狀的元素構成,該元素是內存管理的最小單位。每個元素有8個小電容,存儲8個bit,即1字節。
是否是和磁盤塊差很少, ^_^ 。吒吒輝懂你呀
爲提升系統的存取速度,在 <span style="color:#773098;font-weight:bold;"> 地址映射機制中增長了一個小容量的聯想寄存器,即塊表。 shell
它 <span style="color:#773098;font-weight:bold;"> 用來存放當前訪問最頻繁的少數活動頁面的頁數。當某用戶需存取數據時,根據數據所在的邏輯頁號在塊表中找到對應的內存塊號,再聯繫其頁內地址,造成物理地址。
總結:讀取數據時-->先找邏輯頁--->排查內存塊號--->得到物理層內存表示頁內地址---->物理地址
若是塊表中沒有相應的邏輯頁號,則地址映射仍然能夠經過內存中的頁表進行操做,只是它獲得是空閒塊號,必須將該塊號填入塊表中的空閒區。若是塊表中沒有空閒區,則根據淘汰算法淘汰塊表中的某一行,在填入新的頁號和塊號。
我記得計算機獲取緩存是按照就近原則的,那它們的優先級呢?
緩存會根據存儲速度來選擇最合適的存儲器,離CPU越近的存儲器,速度越快,每字節的成本越高,同時容量也所以越小
分層以下:寄存器(離CPU最近,寄存器速度最快)、高速緩存(緩存也是分級,有L1,L2等緩存)、主存(普通內存)、本地磁盤
平常開發常使緩存軟件,根據軟件系統所處位置不一樣,可分
多級緩存就相似金字塔模式。從上到下依次遞減。相似於一個漏斗來過濾流量請求。若是絕大多數請求在客戶端和網絡交互的部分就抵消,那後端服務的壓力就會大大減小。
根本在於爲網站提供高性能服務,讓用戶具備更好的用戶體驗。以較少的成本獲取更大的性能空間。
用戶體驗這個詞最先被普遍認知是在20世紀90年代中期,由用戶體驗設計師唐納德·諾曼(Donald Norman)提出和推廣。
因信息技術在移動和圖像處理等方面取得的進展已經使得人機交互(HCI)技術幾乎滲透到人類活動的全部領域。這致使系統的評價指標從單純的可用性,擴展到用戶體驗。
用戶體驗在人機交互技術發展過程當中受到了至關的重視,其關注度與 <span style="color:#773098;font-weight:bold;">傳統的三大可用性指標(即效率、效益和基本主觀滿意度不相上下,甚至在某些方面更爲重要。
ISO 9241-210 標準將用戶體驗定義爲 <span style="color:#773098;font-weight:bold;">「人們對正在使用或指望使用的產品、系統或者服務的認知印象和迴應」 。所以,用戶體驗是主觀的,且注重實際應用。
<span style="color:#773098;font-weight:bold;">用戶體驗:即用戶在使用一個產品或系統以前、使用期間和使用以後的所有感覺,包括情感、信仰、喜愛、認知印象、生理反應、心理反應、行爲和成就等各個方面。
ISO標準也暗示了可用性也能夠做爲用戶體驗的一個方面,<span style="color:#773098;font-weight:bold;">「可用性標準能夠用來評估用戶體驗的一些方面」。不過,該ISO標準並無進一步闡述用戶體驗和系統可用性之間的具體關係。顯然,這二者是相互重疊的概念。
也許這就是產品不斷折騰咱技術的緣由,多少得懂點。不知你家產品如何?有無da人的衝動
影響用戶體驗的三因素:
<span style="color:#773098;font-weight:bold;">系統性能是軟件產品自身對用戶體驗最關鍵的因素。 因感覺軟件性能的主體是人,<span style="color:#773098;font-weight:bold;">不一樣的人對於一樣的軟件可能有不一樣的主觀感覺,並且對於軟件性能關心的視角也不一樣。
系統性能是一種非功能特性,<span style="color:#773098;font-weight:bold;">它關注的不是某種特定的功能,而是在完成該功能時所展現出的及時性。
系統性能的指標通常包括 響應時間、延遲時間、吞吐量,併發用戶數和資源利用率 等幾方面。
響應時間是指系統對用戶請求作出響應的時間
,與人對軟件性能的主觀感覺是一致的,完整地記錄了整個系統處理請求的時間。
通常響應時間根據不一樣項目中的業務場景都會有確切的值,例:一個請求需保證在100ms、200ms之內。
你家首頁響應需多少時間?
因爲一個系統一般會提供許多功能,而不一樣功能的處理邏輯也千差萬別,於是不一樣功能的響應時間也不盡相同,甚至同一功能在不一樣輸入數據的狀況下,響應時間也不相同。
因此,咱們常說的響應時間一般指該軟件系統 <span style="color:#773098;font-weight:bold;">全部功能的平均響應時間 或者 <span style="color:#773098;font-weight:bold;">全部功能中的最大響應時間。
有時候也須要對 <span style="color:#773098;font-weight:bold;">每一個或每組功能討論其平均響應時間和最大響應時間。
在討論軟件性能時,咱們更關心所開發軟件自身的 <span style="color:#773098;font-weight:bold;">「響應時間」。
好比:PHP響應時間就是從接受到nginx請求後,並完成業務處理而後響應給nginx所消耗的時間。而用戶就看發送請求到看到頁面所需的時間
前者是整個軟件自身的響應,後者是用戶請求響應的時間。觀看角度不一樣
就這樣,咱們能夠把 用戶感覺到的響應時間 劃分爲 <span style="color:#773098;font-weight:bold;"> 呈現時間和系統響應時間,
服務器響應給客戶端所需的時間**
還能夠把「系統響應時間」
進一步分解爲網絡傳輸時間和「應用延遲時間」,
之後談優化,那就應該從整個請求鏈路裏着手,針對呈現、網絡傳輸、應用處理時間
吞吐量 是指系統在單位時間內處理請求的數量。
單位時間是項目自身規劃響應時間來進行描述的,但經常使用 1s 來衡量處理成功的請求量。
那我網站的吞吐量怎麼計算呢? 做爲小吒的我,仍是補了課的
要計算吞吐量首先要看你的時間換算和流量狀況。
假設一個發佈系統的廣告頁要知足30分鐘內總訪問量爲500w。
那平均QPS爲: 500w/(30*60) = 2778,大概3000 QPS /S(要預留空間)
假設某個信息分類網站首頁日均PV約8000w
那平均QPS爲: 一天按照4W秒算(晚上不計算),8000w/4w= 2000,大概2000QPS。
注:
用戶不會全天都使用軟件,通常晚上不會使用或者使用人不多。但也分業務,你像直播、外賣等。 但一天12小時基本上知足一個用戶當天最大使用軟件的時間。
具體用戶在線使用APP的時間也不肯定,具體應該根據自身項目統計用戶的使用時間和總流量來計算平均QPS。利用高峯期流量來計算最大QPS。
對於無併發的應用系統而言,吞吐量與響應時間成嚴格的反比關係,實際上此時吞吐量就是響應時間的倒數。
無併發的應用都是單機應用,對於互聯網或者移動互聯網上的產品而言。
併發用戶數是指系統能夠同時承載的正常使用系統功能的用戶數量,值越大,那處理能力就越強。
資源利用率反映的是在一段時間內資源平均被佔用的狀況。
從瀏覽器--->網絡--->應用服務器--->數據庫,經過在各個層面應用緩存技術,將大幅提升提高整個系統的性能。
例如:緩存離客戶端更近,從緩存請求內容比從源服務器所用時間更少,呈現速度更快,系統就顯得更靈敏。緩存數據的重複使用,大大下降了用戶的帶寬使用,其實也是一種變相的省錢(若是流量要付費的話),同時保證了帶寬請求在一個低水平上,更容易維護。因此,使用 <span style="color:#773098;font-weight:bold;"> 緩存技術,能夠下降系統的響應時間,減小網絡傳輸時間和應用延遲時間,進而提升了系統的吞吐量,增長了系統的併發用戶數
利用緩存還能夠最小化系統的工做量,使用了緩存就能夠沒必要反覆從數據源中查找,緩存所建立或提供的同一條數據更好地利用了系統的資源。
所以,緩存是系統調優時經常使用且行之有效的手段,不管是操做系統仍是應用系統,緩存策略無處不在。「緩存爲王」本質上是系統性能爲王,對用戶而言就是用戶體驗爲王。
最初的網站可能就是一臺物理主機,放在IDC或者租用的是雲服務器,上面只運行着 <span style="color:#773098;font-weight:bold;">應用服務器和數據庫,LAMP(Linux Apache MySQL PHP)就是這樣流行起來的。
因爲網站具有必定的特點,吸引了部分用戶的訪問,逐漸會發現系統的壓力愈來愈大,響應速度愈來愈慢,而這個時候比較明顯的每每是 <span style="color:#773098;font-weight:bold;">數據庫與應用 的互相影響,因而將應用服務器和數據庫服務器從物理上分離開來,變成了兩臺機器。讓其不在互相影響,來支撐更高的流量。
### 中期
隨着訪問網站的人數愈來愈多,響應速度又開始變慢了,多是 <span style="color:#773098;font-weight:bold;">訪問數據庫的操做太多,致使數據鏈接競爭激烈,所以緩存開始登場。
這裏不難看出,數據庫每每是考慮優化的首選,畢竟沒緩存請求直連數據庫,而數據庫又是數據的集中地,查數據還會涉及磁盤I/O。壓力可想而知
若想經過緩存機制來減小數據庫鏈接資源的競爭和對數據庫讀的壓力,那麼可以下選擇:
靜態緩存更傾向於靜態資源的緩存和瀏覽器的緩存。動態緩存是經過頁面訪問後,在編譯生成緩存文件,提供給後續請求訪問。有點像模板引擎
那我數據庫寫呢?
此刻流量上升,主要針對訪問,寫請求也會上升,但性能瓶頸在於數據庫的讀操做上。能夠說寫還構不成太大的威脅。若是寫不夠,那隻能擴容多個實例來應對寫的不足。
隨着訪問量的持續增長,系統又開始變慢,怎麼辦?
使用 <span style="color:#773098;font-weight:bold;">數據緩存,將系統中重複獲取的數據信息從數據庫加載到本地,同時下降了數據庫的負載。 隨着系統訪問量的再度增長,應用服務器又扛不住了,就開始增長Web服務器。
那如何保持應用服務器中數據緩存信息的同步呢?
例如: 以前緩存的用戶數據等,這個時候一般會開始使用緩存同步機制以及共享文件系統或共享存儲等。 在享受了一段時間的訪問量高速增加後,系統再次變慢。
<span style="color:#773098;font-weight:bold;">開始數據庫調優,優化數據庫自身的緩存,接下來是採用數據庫集羣以及分庫分表的策略。
分庫分表的規則是有些複雜的,考慮增長一個通用的框架來實現分庫分表的數據訪問,這個就是 數據訪問層(Data Access Layer,DAL)。
該階段可能會發現以前的緩存同步方案會出現問題,<span style="color:#773098;font-weight:bold;">由於數據量太大,致使如今不太可能將緩存存儲在本地後再同步,這樣會形成同步的時間延遲從而增大響應時間、數據不一致性,數據庫耦合緩存。
因而分佈式緩存終於來了,將大量的數據緩存轉移到分佈式緩存上。
若是使用共享文件系統或共享存儲有啥問題?
至此,系統進入了無級縮放的大型網站階段,當網站流量增長時,應對的解決方案就是不斷添加Web服務器、數據庫服務器、以及緩存服務器。此時,大型網站的系統架構演變爲圖所示。
縱觀網站架構的發展歷程,緩存技術每每就是解除煩惱的靈丹妙藥,這再次證實了什麼是緩存爲王。
客戶端緩存相對於其餘端的緩存而言,要簡單一些,一般是和服務端以及網絡側的應用或緩存配合使用。
在互聯網應用中,根據應用區分有二大類。
頁面緩存是什麼?
頁面緩存有兩層含義:
頁面緩存是將以前渲染的頁面保存爲靜態文件,當用戶再次訪問時能夠避開網絡鏈接,從而減小負載,提高性能和用戶體驗。
隨着單頁面應用(Single Page Application,SPA)的普遍使用,加之HTML5支持了離線緩存和本地存儲,大部分BS應用的頁面緩存均可以舉重若輕了。
在HTML5中使用本地緩存的方法,示例代碼以下:
localStorage.setItem("mykey","吒吒輝") localStorage.getItem("mykey","吒吒輝") localStorage.removeItem("mykey") localStorage.clear()
什麼是單頁面應用?
SPA是在 Web 設計上使用單一頁面,利用 JavaScript 操做 Dom 的技術實現各類應用。此模式下一個系統只加載一次資源,以後的操做交互、數據交互是經過路由、ajax來進行,頁面並無刷新。常見的路由形式如:http:.//xxx/shell.htm1#page1。
通常在Vue下使用很明顯。像商城活動頁、登陸頁這種都是很好的SPA落地實踐。
HTML5提供的離線應用緩存機制,使得網頁應用能夠離線使用(無網絡也可訪問),這種機制在瀏覽器上支持度很是廣,能夠放心地使用該特性來加速頁面的訪問。開啓離線緩存的步驟以下:
(manifest text/cache-manifest)
。注:manifest 文件須要配置正確的 MIME-type,即 "text/cache-manifest"。必須在 web 服務器上進行配置。
例:nginx要修改配置目錄下的 mime.types 文件,添加manifest文件映射:
text/cache-manifest manifest;
manifest
屬性,指定緩存清單文件的路徑。 離線緩存的工做流如圖所示。`
目前html標籤的manifest屬性已廢棄了,可移步 webpack。
`
由圖可知:
manifest
屬性的頁面時,若是應用的緩存不存在,瀏覽器會加載文檔,獲取全部在清單文件中列出的文件,生成初始緩存。window.applicationCache
對象發送一個表示檢查的事件,以獲取清單文件。 window.applicationCache
對象發送一個表示進行中的事件。注意:manifest文件中列出的資源URL必須和manifest自己使用一樣的網絡協議,詳情可參考W3C相關的標準文檔。
*
瀏覽器緩存是根據一套與服務器約定的規則進行工做的,工做規則很簡單:檢查以確保副本爲最新,一般只要一次會話請求。
瀏覽器會在硬盤上專門開闢一個空間來存儲資源副本做爲緩存。
在用戶觸發 <span style="color:#773098;font-weight:bold;">後退操做或點擊 一個以前看過連接的時候,瀏覽器緩存會很管用。若是訪問系統中的同一張圖片,該圖片能夠從瀏覽器緩存中調出並幾乎當即顯現出來。
對瀏覽器而言,HTTP1.0提供了一些很基本的緩存特性,參數例如:
每次請求web容器時會先檢查客戶端緩存資源是否還有效,無效則會把上次服務端響應的最後修改時間做爲 If-Modified-Since 的值發送給服務器進行判斷,若是文件沒有改變,服務器採用 <span style="color:#773098;font-weight:bold;">304-Not Modified作響應頭和一個爲空的響應體。客戶端收到304響應,就可使用緩存的文件版本了。
爲何客戶端無效,還要發送HTTP請求來判斷文件是否修改呢?
若是緩存資源有效那確實直接來讀取客戶端緩存,不須要發送HTTP請求。但有一些狀況就需注意,好比當用戶按F5或者點擊Refresh按鈕的時候就算對於有Expires的URI,同樣也會發一個HTTP請求出去,因此就須要經過Last-Modified來判斷。
並且客戶端和服務端的時間可能不同,這樣就會致使客戶端已過時,但服務端並無。若是有判斷機制,那麼響應就會減小響應體的數據發送。 或者客戶端只是單純的 Expires 過時,但資源並沒改變,這時就須要檢查文件是否有變化。
HTTP 1.1有了較大的加強,緩存系統被形式化了,引入了實體標籤 **<span style="color:#773098;font-weight:bold;">e-tag 和 Cache-Control。
Cache-Control:相對過時,從客戶端收到響應時間時開始計算,多少秒後緩存會過時。 具體字段信息以下:
- public:指示響應可被任何緩存區緩存;
以Web瀏覽器使用 e-tag
爲例,以下圖所示。
在配置了 Last-Modified/ETag 的狀況下,瀏覽器再次訪問統一URI的資源時,仍是會發送請求到服務器詢問文件是否已經修改,若是沒有,服務器會生成304-Not Modified應答和一個空的響應體給瀏覽器,瀏覽器則直接從本地緩存取數據;若是數據有變化,就將整個數據從新發給瀏覽器。
Last-Modified/ETag 與 Cache-Control/Expires的做用是不同的。前者是每次詢問實體版本是否有變化,後者是直接檢查本地的緩存還在有效的時間範圍內,若是在就不會發送任何請求。
當本地副本根據 Cache-Control/Expires 判斷是否還在有效期內,若是不在,則會再次發送請求去服務器詢問修改時間(Last-Modified)或實體標識(e-tag)。
Cache-Control與Expires的功能一致,都是指當前資源的有效期,控制瀏覽器是直接從瀏覽器緩存取數據仍是從新發請求到服務器取數據。只不過Cache-Control的選擇更多,設置更細緻,若是同時設置的話,其優先級高於Expires。
通常狀況下,使用 Cache-Control/Expires 會配合 Last-Modified/ETag 一塊兒使用,由於即便服務器設置緩存時間,當用戶點擊 <span style="color:#773098;font-weight:bold;"> 刷新 按鈕時,瀏覽器會忽略緩存繼續向服務器發送請求,這時Last-Modified/ETag將可以很好利用服務端的返回碼304,從而減小響應開銷。
經過在HTML頁面的節點中加入meta標籤,可告訴瀏覽器當前頁面不被緩存,每次訪問都須要去服務器拉取。代碼以下:
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
只不過,只有部分瀏覽器才支持這一用法,並且通常 <span style="color:#773098;font-weight:bold;"> 緩存代理服務器都不支持,由於代理自己不解析 HTML 的內容。 瀏覽器緩存可以極大地提高終端用戶的體驗,那麼,用戶在使用瀏覽器的時候,會有各類操做,如輸入地址後回車、按F5刷新等等,這些行爲對緩存的影響以下所示。
儘管混合編程(hybrid programming)已成爲時尚,吵在尖端,但移動互聯網目前仍是原生應用(APP)的天下。不管大小型APP,靈活的緩存不只大大減輕了服務器的壓力,並且會因更快速的用戶體驗而方便用戶。<span style="color:#773098;font-weight:bold;"> 如何把APP 緩存對於業務組件透明,以及APP緩存數據的及時更新,是APP緩存可否成功應用起來的關鍵。
組件透明是什麼?
即組件對調用者來講沒有什麼影響,也不須要維護。開箱即用。
APP緩存可以使用那些緩存?
APP能夠將內容緩存在 <span style="color:#773098;font-weight:bold;">內存、文件或本地數據庫(例如SQLite)中,但基於 <span style="color:#773098;font-weight:bold;"> 內存的緩存 要謹慎使用。
APP使用數據庫緩存的方法:
優勢:方法具備靈活存放文件的屬性,進而提供了很大的擴展性,能夠爲其餘的功能提供良好的支持。
缺點:信息存儲過多,存儲容量會下降。因此要根據業務選擇合適主要的信息存儲
<span style="color:#773098;font-weight:bold;">注意數據庫緩存的清理機制 。
對APP中的某些界面,能夠採用文件緩存的方法。這種方法使用文件操做的相關API獲得文件的最後修改時間,與當前時間判斷是否過時,從而實現緩存效果。
但須要注意的是,<span style="color:#773098;font-weight:bold;">不一樣類型文件的緩存時間不同。好比:
<span style="color:#773098;font-weight:bold;">文件類型:
<span style="color:#773098;font-weight:bold;">網絡環境:
在iOS開發中,SDWebImage是一個很棒的圖片緩存框架,主要類組成的結構以下所示。
SDWebImage 是個比較大的類庫,提供一個UIImageView的類以支持遠程加載來自網絡的圖片,具備緩存管理、異步下載、同一個URL下載次數控制和優化等特徵。使用時,只須要在頭文件中引入
#import"UIImageView+WebCache.h"
便可調用異步加載圖片方法:
(void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
URL是圖片的地址
默認狀況下,SDWebImage會忽略Header中的緩存設置,將圖片以URL爲key進行保存,URL與圖片是一一映射關係。在APP請求同一個URL時,SDWebImage會從緩存中取得圖片。將第三個參數設置爲SDWebImageRefreshCached就能夠實現圖片更新操做,例如:
NSURL *url = [NSURL URLWithString:@"http://www.zhazhahui.com/image.png"]; UIImage *defaultImage = [UIImage imageNamed:@"zhazhahui.png"]; [self.imageView setImageWithURL:url placeholderImage:defaultImage options:SDWebImageRefreshCached];
SDWebImage中有兩種緩存
框架都提供了相應的清理方法:
[[[SDWebImageManager sharedManager] imageCache] clearDisk]; [[[SDWebImageManager sharedManager] imageCache] clearMemory];
要注意的是,在iOS7中,緩存機制作了修改,使用上述兩個方法只清除了SDWebImage的緩存, 沒有清除系統的緩存,因此能夠在清除緩存的代理中添加如下代碼:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
以上就是本文分享,但內容未完,這仍是開胃小菜。如有幫助,歡迎關注、分享。
需獲取本系列總結大綱直接公衆號後臺回覆「分佈式緩存」便可免費領取!!!
其實,大綱很早就寫好了,但對裏面內容的呈現方式,細節原理就一直不知道如何撰寫才能達到明朗的效果。
這文章花了我很是多時間。哎,菜就是菜,吒吒輝我也不找藉口了。。。 吒就是吒
最近吒吒輝創了技術交流羣,主題就是 【知識盛宴】,你們一塊兒每週攻克一個難題,充分進行自我能力迭代提高,不單純技術額!!!
有興趣的讀者,能夠掃一掃吒吒輝微信二維碼,備註 「加羣」 便可。據說裏面的人說話又好聽,各個都是人才。
若是你們在閱讀過程當中,發現了不理解或有錯誤的地方,歡迎跟在底部留言,大家的每一條留言,吒吒輝都會回覆。
若有幫助,歡迎關注、分享+收藏額,微信搜索【蓮花童子哪吒】