一談緩存,內(nèi)心頓時豁然開朗。迫于key-value的形式,總感覺輕風(fēng)扶面,楊柳依依,一切都盡在我掌握之中。猶如那一眼相中佳人的沖動,腦子里盡是佳人的容顏。
那緩存如果站在網(wǎng)站架構(gòu)的角度,你知道它的設(shè)計原理和影響作用嗎?
絮叨
在商業(yè)的世界里,常說的一句話是 "現(xiàn)金為王"。在互聯(lián)網(wǎng)、移動互聯(lián)網(wǎng)乃至整個軟件技術(shù)的世界里面,與之相近的就是 "緩存為王"。
為何這么說呢?
試想一下,你個完整的網(wǎng)絡(luò)請求(HTTP、SOAP、RPC等),如果在執(zhí)行過程的某個部分尚有緩存,是不是就能提前響應(yīng)給客戶端呢?
為何現(xiàn)在很多中大型公司在面試時,對緩存的應(yīng)用、原理、高可用等一系列問題,都一撲啦的扔給你,讓你難以招架。原因都在這。
什么是緩存?
緩存:存儲在計算機上的一個原始數(shù)據(jù)復(fù)制,以便于訪問
緩存是系統(tǒng)快速響應(yīng)中的一種關(guān)鍵技術(shù),是一組被保存起來以備將來使用的東西。介于應(yīng)用開發(fā)和系統(tǒng)開發(fā)之間,是產(chǎn)品經(jīng)理經(jīng)常估計不到的地方,也是技術(shù)架構(gòu)設(shè)計中的非功能性約束。
應(yīng)用開發(fā)我知道,這系統(tǒng)緩存是個什么情況呀,小吒哥?
不要著急,往后面看
什么是多級緩存架構(gòu)?
顧名思義,由多個維度共同組成的緩存工程。因為緩存在不同的場景有著不同的意義。采用的技術(shù)手段也不同。
按緩存存在形式分:
1. 硬件緩存(如CPU、硬盤等)
2. 操作系統(tǒng)緩存
3. 軟件緩存
系統(tǒng)緩存是什么?
操作系統(tǒng)是管理計算機硬件與軟件資源的計算機程序,而硬、軟件件運行速度的快慢基本由緩存決定,緩存的容量越大,相應(yīng)的硬件運行速度也就越快。所以系統(tǒng)緩存就是操作系統(tǒng)調(diào)用硬件資源(內(nèi)存、文件等)和調(diào)用應(yīng)用程序時,能夠啟動加速執(zhí)行的作用。
總結(jié):操作系統(tǒng)存調(diào)用涉及到有緩存的部分,都可算系統(tǒng)緩存
軟件運行都需建立在操作系統(tǒng)之上,在運行時需要把程序裝載到內(nèi)存中,但軟件執(zhí)行操作內(nèi)存時都是基于虛擬內(nèi)存映射的機制,并不是直接操作物理內(nèi)存。虛擬內(nèi)存以塊表(內(nèi)存塊組成的表格)的形式來存儲相關(guān)資源。
注:物理內(nèi)存組成上由多個方塊狀的元素構(gòu)成,該元素是內(nèi)存管理的最小單位。每一個元素有8個小電容,存儲8個bit,即1字節(jié)。
是不是和磁盤塊差不多
為提高系統(tǒng)的存取速度,在 地址映射機制中增加了一個小容量的聯(lián)想寄存器,即塊表。
它 用來存放當(dāng)前訪問最頻繁的少數(shù)活動頁面的頁數(shù)。當(dāng)某用戶需存取數(shù)據(jù)時,根據(jù)數(shù)據(jù)所在的邏輯頁號在塊表中找到對應(yīng)的內(nèi)存塊號,再聯(lián)系其頁內(nèi)地址,形成物理地址。
總結(jié):讀取數(shù)據(jù)時-->先找邏輯頁--->排查內(nèi)存塊號--->獲得物理層內(nèi)存表示頁內(nèi)地址---->物理地址
如果塊表中沒有相應(yīng)的邏輯頁號,則地址映射仍然可以通過內(nèi)存中的頁表進(jìn)行操作,只是它得到是空閑塊號,必須將該塊號填入塊表中的空閑區(qū)。如果塊表中沒有空閑區(qū),則根據(jù)淘汰算法淘汰塊表中的某一行,在填入新的頁號和塊號。
我記得計算機獲取緩存是按照就近原則的,那它們的優(yōu)先級呢?
緩存會根據(jù)存儲速度來選擇最合適的存儲器,離CPU越近的存儲器,速度越快,每字節(jié)的成本越高,同時容量也因此越小
分層如下:寄存器(離CPU最近,寄存器速度最快)、高速緩存(緩存也是分級,有L1,L2等緩存)、主存(普通內(nèi)存)、本地磁盤
日常開發(fā)常使緩存軟件,根據(jù)軟件系統(tǒng)所處位置不同,可分
- 客戶端緩存
- 網(wǎng)絡(luò)緩存
- 服務(wù)端緩存
多級緩存就類似金字塔模式。從上到下依次遞減。類似于一個漏斗來過濾流量請求。如果絕大多數(shù)請求在客戶端和網(wǎng)絡(luò)交互的部分就抵消,那后端服務(wù)的壓力就會大大減少。
為什么使用多級緩存架構(gòu)?
根本在于為網(wǎng)站提供高性能服務(wù),讓用戶具有更好的用戶體驗。以較少的成本獲取更大的性能空間。
聊聊用戶體驗
用戶體驗這個詞最早被廣泛認(rèn)知是在20世紀(jì)90年代中期,由用戶體驗設(shè)計師唐納德·諾曼(Donald Norman)提出和推廣。
因信息技術(shù)在移動和圖像處理等方面取得的進(jìn)展已經(jīng)使得人機交互(HCI)技術(shù)幾乎滲透到人類活動的所有領(lǐng)域。這導(dǎo)致系統(tǒng)的評價指標(biāo)從單純的可用性,擴展到用戶體驗。
用戶體驗在人機交互技術(shù)發(fā)展過程中受到了相當(dāng)?shù)闹匾暎潢P(guān)注度與 傳統(tǒng)的三大可用性指標(biāo)(即效率、效益和基本主觀滿意度不相上下,甚至在某些方面更為重要。
什么是用戶體驗?
ISO 9241-210 標(biāo)準(zhǔn)將用戶體驗定義為 “人們對正在使用或期望使用的產(chǎn)品、系統(tǒng)或者服務(wù)的認(rèn)知印象和回應(yīng)” 。因此,用戶體驗是主觀的,且注重實際應(yīng)用。
用戶體驗:即用戶在使用一個產(chǎn)品或系統(tǒng)之前、使用期間和使用之后的全部感受,包括情感、信仰、喜好、認(rèn)知印象、生理反應(yīng)、心理反應(yīng)、行為和成就等各個方面。
ISO標(biāo)準(zhǔn)也暗示了可用性也可以作為用戶體驗的一個方面,“可用性標(biāo)準(zhǔn)可以用來評估用戶體驗的一些方面”。不過,該ISO標(biāo)準(zhǔn)并沒有進(jìn)一步闡述用戶體驗和系統(tǒng)可用性之間的具體關(guān)系。顯然,這兩者是相互重疊的概念。
也許這就是產(chǎn)品不斷折騰咱技術(shù)的原因,多少得懂點。不知你家產(chǎn)品如何?有無da人的沖動
影響用戶體驗的因素
影響用戶體驗的三因素:
- 使用者的狀態(tài)
- 系統(tǒng)性能
- 環(huán)境
系統(tǒng)性能是軟件產(chǎn)品自身對用戶體驗最關(guān)鍵的因素。 因感受軟件性能的主體是人,不同的人對于同樣的軟件可能有不同的主觀感受,而且對于軟件性能關(guān)心的視角也不同。
系統(tǒng)性能是一種非功能特性,它關(guān)注的不是某種特定的功能,而是在完成該功能時所展示出的及時性。
關(guān)于系統(tǒng)的性能
系統(tǒng)性能的指標(biāo)一般包括 響應(yīng)時間、延遲時間、吞吐量,并發(fā)用戶數(shù)和資源利用率 等幾方面。
響應(yīng)時間
響應(yīng)時間是指系統(tǒng)對用戶請求做出響應(yīng)的時間,與人對軟件性能的主觀感受是一致的,完整地記錄了整個系統(tǒng)處理請求的時間。
一般響應(yīng)時間根據(jù)不同項目中的業(yè)務(wù)場景都會有確切的值,例:一個請求需保證在100ms、200ms以內(nèi)。
你家首頁響應(yīng)需多少時間?
由于一個系統(tǒng)通常會提供許多功能,而不同功能的處理邏輯也千差萬別,因而不同功能的響應(yīng)時間也不盡相同,甚至同一功能在不同輸入數(shù)據(jù)的情況下,響應(yīng)時間也不相同。
所以,我們常說的響應(yīng)時間通常指該軟件系統(tǒng) 所有功能的平均響應(yīng)時間 或者 所有功能中的最大響應(yīng)時間。
有時候也需要對 每個或每組功能討論其平均響應(yīng)時間和最大響應(yīng)時間。
在討論軟件性能時,我們更關(guān)心所開發(fā)軟件自身的 “響應(yīng)時間”。
比如:PHP響應(yīng)時間就是從接受到nginx請求后,并完成業(yè)務(wù)處理然后響應(yīng)給nginx所消耗的時間。而用戶就看發(fā)送請求到看到頁面所需的時間
前者是整個軟件自身的響應(yīng),后者是用戶請求響應(yīng)的時間。觀看角度不同
就這樣,我們可以把 用戶感受到的響應(yīng)時間 劃分為 呈現(xiàn)時間和系統(tǒng)響應(yīng)時間,
- 呈現(xiàn)時間:客戶端在接收到系統(tǒng)數(shù)據(jù)時呈現(xiàn)頁面所需的時間,即頁面渲染加載時間,
- 系統(tǒng)響應(yīng)時間:從客戶端發(fā)送請求開始計時,直到 服務(wù)器響應(yīng)給客戶端所需的時間
還可以把“系統(tǒng)響應(yīng)時間”進(jìn)一步分解為網(wǎng)絡(luò)傳輸時間和“應(yīng)用延遲時間”,
- 網(wǎng)絡(luò)傳輸時間:數(shù)據(jù)在客戶端和服務(wù)器端進(jìn)行傳輸?shù)臅r間
- 應(yīng)用延遲時間:系統(tǒng)實際處理請求業(yè)務(wù)所需時間
以后談優(yōu)化,那就應(yīng)該從整個請求鏈路里著手,針對呈現(xiàn)、網(wǎng)絡(luò)傳輸、應(yīng)用處理時間
吞吐量
吞吐量 是指系統(tǒng)在單位時間內(nèi)處理請求的數(shù)量。
單位時間是項目自身規(guī)劃響應(yīng)時間來進(jìn)行描述的,但常用 1s 來衡量處理成功的請求量。
那我網(wǎng)站的吞吐量怎么計算呢?作為小吒的我,還是補了課的
要計算吞吐量首先要看你的時間換算和流量情況。
- 單位時間劃分
假設(shè)一個發(fā)布系統(tǒng)的廣告頁要滿足30分鐘內(nèi)總訪問量為500w。
那平均QPS為:500w/(30*60) = 2778,大概3000 QPS /S(要預(yù)留空間) - 按天算
假設(shè)某個信息分類網(wǎng)站首頁日均PV約8000w
那平均QPS為:一天按照4W秒算(晚上不計算),8000w/4w= 2000,大概2000QPS。
注:
用戶不會全天都使用軟件,一般晚上不會使用或者使用人很少。但也分業(yè)務(wù),你像直播、外賣等。但一天12小時基本上滿足一個用戶當(dāng)天最大使用軟件的時間。
具體用戶在線使用APP的時間也不確定,具體應(yīng)該根據(jù)自身項目統(tǒng)計用戶的使用時間和總流量來計算平均QPS。利用高峰期流量來計算最大QPS。
對于無并發(fā)的應(yīng)用系統(tǒng)而言,吞吐量與響應(yīng)時間成嚴(yán)格的反比關(guān)系,實際上此時吞吐量就是響應(yīng)時間的倒數(shù)。
無并發(fā)的應(yīng)用都是單機應(yīng)用,對于互聯(lián)網(wǎng)或者移動互聯(lián)網(wǎng)上的產(chǎn)品而言。
并發(fā)用戶數(shù)
并發(fā)用戶數(shù)是指系統(tǒng)可以同時承載的正常使用系統(tǒng)功能的用戶數(shù)量,值越大,那處理能力就越強。
資源利用率反映的是在一段時間內(nèi)資源平均被占用的情況。
從瀏覽器--->網(wǎng)絡(luò)--->應(yīng)用服務(wù)器--->數(shù)據(jù)庫,通過在各個層面應(yīng)用緩存技術(shù),將大幅提高提升整個系統(tǒng)的性能。
例如:緩存離客戶端更近,從緩存請求內(nèi)容比從源服務(wù)器所用時間更少,呈現(xiàn)速度更快,系統(tǒng)就顯得更靈敏。緩存數(shù)據(jù)的重復(fù)使用,大大降低了用戶的帶寬使用,其實也是一種變相的省錢(如果流量要付費的話),同時保證了帶寬請求在一個低水平上,更容易維護(hù)。
所以,使用 緩存技術(shù),可以降低系統(tǒng)的響應(yīng)時間,減少網(wǎng)絡(luò)傳輸時間和應(yīng)用延遲時間,進(jìn)而提高了系統(tǒng)的吞吐量,增加了系統(tǒng)的并發(fā)用戶數(shù)
利用緩存還可以最小化系統(tǒng)的工作量,使用了緩存就可以不必反復(fù)從數(shù)據(jù)源中查找,緩存所創(chuàng)建或提供的同一條數(shù)據(jù)更好地利用了系統(tǒng)的資源。
因此,緩存是系統(tǒng)調(diào)優(yōu)時常用且行之有效的手段,無論是操作系統(tǒng)還是應(yīng)用系統(tǒng),緩存策略無處不在。“緩存為王”本質(zhì)上是系統(tǒng)性能為王,對用戶而言就是用戶體驗為王。
網(wǎng)站架構(gòu)緩存演進(jìn)
起步
最初的網(wǎng)站可能就是一臺物理主機,放在IDC或者租用的是云服務(wù)器,上面只運行著 應(yīng)用服務(wù)器和數(shù)據(jù)庫,LAMP(Linux Apache MySQL PHP)就是這樣流行起來的。
發(fā)展
由于網(wǎng)站具備一定的特色,吸引了部分用戶的訪問,逐漸會發(fā)現(xiàn)系統(tǒng)的壓力越來越大,響應(yīng)速度越來越慢,而這個時候比較明顯的往往是 數(shù)據(jù)庫與應(yīng)用 的互相影響,于是將應(yīng)用服務(wù)器和數(shù)據(jù)庫服務(wù)器從物理上分離開來,變成了兩臺機器。讓其不在互相影響,來支撐更高的流量。
中期
隨著訪問網(wǎng)站的人數(shù)越來越多,響應(yīng)速度又開始變慢了,可能是 訪問數(shù)據(jù)庫的操作太多,導(dǎo)致數(shù)據(jù)連接競爭激烈,因此緩存開始登場。
這里不難看出,數(shù)據(jù)庫往往是考慮優(yōu)化的首選,畢竟沒緩存請求直連數(shù)據(jù)庫,而數(shù)據(jù)庫又是數(shù)據(jù)的集中地,查數(shù)據(jù)還會涉及磁盤I/O。壓力可想而知
若想通過緩存機制來減少數(shù)據(jù)庫連接資源的競爭和對數(shù)據(jù)庫讀的壓力,那么可如下選擇:
- 靜態(tài)頁面緩存: 這樣程序上可以不做修改,就能夠很好地減少對Web服務(wù)器的壓力以及減少對數(shù)據(jù)庫連接資源的競爭。
- 動態(tài)緩存: 將動態(tài)頁面里相對靜態(tài)的部分也緩存起來,因此考慮采用類似的頁面片段緩存策略(通過nginx、Apache配置實現(xiàn)動態(tài)緩存)。
靜態(tài)緩存更傾向于靜態(tài)資源的緩存和瀏覽器的緩存。動態(tài)緩存是通過頁面訪問后,在編譯生成緩存文件,提供給后續(xù)請求訪問。有點像模板引擎
那我數(shù)據(jù)庫寫呢?
此刻流量上升,主要針對訪問,寫請求也會上升,但性能瓶頸在于數(shù)據(jù)庫的讀操作上??梢哉f寫還構(gòu)不成太大的威脅。如果寫不夠,那只能擴容多個實例來應(yīng)對寫的不足。
高速增長期
隨著訪問量的持續(xù)增加,系統(tǒng)又開始變慢,怎么辦?
使用 數(shù)據(jù)緩存,將系統(tǒng)中重復(fù)獲取的數(shù)據(jù)信息從數(shù)據(jù)庫加載到本地,同時降低了數(shù)據(jù)庫的負(fù)載。隨著系統(tǒng)訪問量的再度增加,應(yīng)用服務(wù)器又扛不住了,就開始增加Web服務(wù)器。
那如何保持應(yīng)用服務(wù)器中數(shù)據(jù)緩存信息的同步呢?
例如:之前緩存的用戶數(shù)據(jù)等,這個時候通常會開始使用緩存同步機制以及共享文件系統(tǒng)或共享存儲等。在享受了一段時間的訪問量高速增長后,系統(tǒng)再次變慢。
開始數(shù)據(jù)庫調(diào)優(yōu),優(yōu)化數(shù)據(jù)庫自身的緩存,接下來是采用數(shù)據(jù)庫集群以及分庫分表的策略。
分庫分表的規(guī)則是有些復(fù)雜的,考慮增加一個通用的框架來實現(xiàn)分庫分表的數(shù)據(jù)訪問,這個就是數(shù)據(jù)訪問層(Data Access Layer,DAL)。
- 緩存同步機制:每臺web服務(wù)器,都會是保存一份緩存文件,那數(shù)據(jù)之間就需要緩存的同步機制來完成。
- 共享存儲:共享存儲是指兩個或多個處理機共用一個主存儲器的并行體系結(jié)構(gòu),像Redis。
- 共享文件系統(tǒng):兩臺機器之間的文件系統(tǒng)能夠更加緊密地結(jié)合在一起,讓一臺主機上的用戶可以像使用本機的文件系統(tǒng)一樣使用遠(yuǎn)程機的文件系統(tǒng)。像Samba和NFS。
后期
該階段可能會發(fā)現(xiàn)之前的緩存同步方案會出現(xiàn)問題,因為數(shù)據(jù)量太大,導(dǎo)致現(xiàn)在不太可能將緩存存儲在本地后再同步,這樣會造成同步的時間延遲從而增大響應(yīng)時間、數(shù)據(jù)不一致性,數(shù)據(jù)庫耦合緩存。
于是分布式緩存終于來了,將大量的數(shù)據(jù)緩存轉(zhuǎn)移到分布式緩存上。
如果使用共享文件系統(tǒng)或共享存儲有啥問題?
- 共享存儲:多個服務(wù)訪問一個存儲,那么容易造成單例性能不足的問題和。如果是并發(fā)讀寫可能會導(dǎo)致緩存和數(shù)據(jù)不一致問題。
- 共享文件:多個服務(wù)壓力太大,因文件I/O開銷大。性能會導(dǎo)致下降。
最終
至此,系統(tǒng)進(jìn)入了無級縮放的大型網(wǎng)站階段,當(dāng)網(wǎng)站流量增加時,應(yīng)對的解決方案就是不斷添加Web服務(wù)器、數(shù)據(jù)庫服務(wù)器、以及緩存服務(wù)器。此時,大型網(wǎng)站的系統(tǒng)架構(gòu)演變?yōu)閳D所示。
縱觀網(wǎng)站架構(gòu)的發(fā)展歷程,緩存技術(shù)往往就是解除煩惱的靈丹妙藥,這再次證明了什么是緩存為王。
客戶端緩存的實施方案
客戶端緩存相對于其他端的緩存而言,要簡單一些,通常是和服務(wù)端以及網(wǎng)絡(luò)側(cè)的應(yīng)用或緩存配合使用。
在互聯(lián)網(wǎng)應(yīng)用中,根據(jù)應(yīng)用區(qū)分有二大類。
- B/S架構(gòu):頁面緩存和瀏覽器緩存
- 移動應(yīng)用:APP自身所使用的緩存
頁面緩存
頁面緩存是什么?
頁面緩存有兩層含義:
- 客戶端將頁面自身對某些元素或全部元素進(jìn)行緩存。簡稱離線應(yīng)用緩存
- 服務(wù)端將靜態(tài)頁面或動態(tài)頁面的元素進(jìn)行緩存,然后給客戶端使用。簡稱頁面自身緩存。
頁面緩存是將之前渲染的頁面保存為靜態(tài)文件,當(dāng)用戶再次訪問時可以避開網(wǎng)絡(luò)連接,從而減少負(fù)載,提升性能和用戶體驗。
隨著單頁面應(yīng)用(Single Page Application,SPA)的廣泛使用,加之HTML5支持了離線緩存和本地存儲,大部分BS應(yīng)用的頁面緩存都可以舉重若輕了。
在HTML5中使用本地緩存的方法,示例代碼如下:
localStorage.setItem("mykey","吒吒輝")
localStorage.getItem("mykey","吒吒輝")
localStorage.removeItem("mykey")
localStorage.clear()
什么是單頁面應(yīng)用?
SPA是在 Web 設(shè)計上使用單一頁面,利用 JavaScript 操作 Dom 的技術(shù)實現(xiàn)各種應(yīng)用。此模式下一個系統(tǒng)只加載一次資源,之后的操作交互、數(shù)據(jù)交互是通過路由、ajax來進(jìn)行,頁面并沒有刷新。
常見的路由形式如:http:.//xxx/shell.htm1#page1。
一般在Vue下使用很明顯。像商城活動頁、登錄頁這種都是很好的SPA落地實踐。
HTML5提供的離線應(yīng)用緩存機制,使得網(wǎng)頁應(yīng)用可以離線使用(無網(wǎng)絡(luò)也可訪問),這種機制在瀏覽器上支持度非常廣,可以放心地使用該特性來加速頁面的訪問。開啟離線緩存的步驟如下:
- 準(zhǔn)備用于描述頁面需要緩存的資源列表清單文件
(manifest text/cache-manifest)。
注:manifest 文件需要配置正確的 MIME-type,即 "text/cache-manifest"。必須在 web 服務(wù)器上進(jìn)行配置。
例:nginx要修改配置目錄下的 mime.types 文件,添加manifest文件映射:
text/cache-manifest manifest;
- 在需要離線使用的頁面中的 html 里添加
manifest屬性,指定緩存清單文件的路徑。離線緩存的工作流如圖所示。
目前html標(biāo)簽的manifest屬性已廢棄了,可移步 webpack。
由圖可知:
當(dāng)瀏覽器訪問一個包含
manifest屬性的頁面時,如果應(yīng)用的緩存不存在,瀏覽器會加載文檔,獲取所有在清單文件中列出的文件,生成初始緩存。當(dāng)后續(xù)請求再次對該文檔再次訪問時,瀏覽器會直接從應(yīng)用緩存中加載頁面以及在清單文件中列出的資源。同時,瀏覽器還會向
window.applicationCache對象發(fā)送一個表示檢查的事件,以獲取清單文件。如果當(dāng)前緩存的清單副本是最新的,瀏覽器將向window.applicationCache對象發(fā)送一個表示無須更新的事件,從而結(jié)束更新過程。如果在服務(wù)端修改了任何緩存資源,必須同時修改清單文件,這樣瀏覽器才能知道要重新獲取資源。
如果清單文件已經(jīng)改變,那么文件中列出的所有文件會被重新獲取并放到一個臨時緩存中。對于每個加入到臨時緩存中的文件,瀏覽器會向
window.applicationCache對象發(fā)送一個表示進(jìn)行中的事件。一旦所有文件都獲取成功,它們會自動移動到真正的離線緩存中,并向window.applicationCache對象發(fā)送一個表示已經(jīng)緩存的事件。鑒于文檔早已經(jīng)從緩存加載到瀏覽器中,所以更新后的文檔不會重新渲染,直到頁面重新加載。
注意:manifest文件中列出的資源URL必須和manifest本身使用同樣的網(wǎng)絡(luò)協(xié)議,詳情可參考W3C相關(guān)的標(biāo)準(zhǔn)文檔。
瀏覽器緩存
瀏覽器緩存是根據(jù)一套與服務(wù)器約定的規(guī)則進(jìn)行工作的,工作規(guī)則很簡單:檢查以確保副本為最新,通常只要一次會話請求。
瀏覽器會在硬盤上專門開辟一個空間來存儲資源副本作為緩存。
在用戶觸發(fā) 后退操作或點擊 一個之前看過鏈接的時候,瀏覽器緩存會很管用。如果訪問系統(tǒng)中的同一張圖片,該圖片可以從瀏覽器緩存中調(diào)出并幾乎立即顯現(xiàn)出來。
HTTP1.0
對瀏覽器而言,HTTP1.0提供了一些很基本的緩存特性,參數(shù)例如:
- 在服務(wù)器側(cè)設(shè)置 Expires的HTTP頭 來告訴客戶端在重新請求文件之前緩存多久是有效的.
- 請求通過 if-modified-since 的條件判斷使用緩存。
- Last-Modified:Last-Modified是響應(yīng)頭,web容器會把最后修改時間告訴客戶端
每次請求web容器時會先檢查客戶端緩存資源是否還有效,無效則會把上次服務(wù)端響應(yīng)的最后修改時間作為 If-Modified-Since 的值發(fā)送給服務(wù)器進(jìn)行判斷,如果文件沒有改變,服務(wù)器采用 304-Not Modified做響應(yīng)頭和一個為空的響應(yīng)體。客戶端收到304響應(yīng),就可以使用緩存的文件版本了。
為什么客戶端無效,還要發(fā)送HTTP請求來判斷文件是否修改呢?
如果緩存資源有效那確實直接來讀取客戶端緩存,不需要發(fā)送HTTP請求。但有一些情況就需注意,比如當(dāng)用戶按F5或者點擊Refresh按鈕的時候就算對于有Expires的URI,一樣也會發(fā)一個HTTP請求出去,所以就需要通過Last-Modified來判斷。
而且客戶端和服務(wù)端的時間可能不一樣,這樣就會導(dǎo)致客戶端已過期,但服務(wù)端并沒有。如果有判斷機制,那么響應(yīng)就會減少響應(yīng)體的數(shù)據(jù)發(fā)送?;蛘呖蛻舳酥皇菃渭兊?Expires 過期,但資源并沒改變,這時就需要檢查文件是否有變化。
HTTP 1.1
HTTP 1.1有了較大的增強,緩存系統(tǒng)被形式化了,引入了實體標(biāo)簽 **e-tag 和 Cache-Control。
e-tag 是文件或?qū)ο蟮奈ㄒ粯?biāo)識。每次請求攜帶e-tage參數(shù)進(jìn)行訪問,文件是否被更新。
Cache-Control:相對過期,從客戶端收到響應(yīng)時間時開始計算,多少秒后緩存會過期。具體字段信息如下:
max-age:用來設(shè)置資源(representations)可以被緩存多長時間,單位為秒;
s-maxage:和max-age是一樣的,不過它只針對代理服務(wù)器緩存而言; - public:指示響應(yīng)可被任何緩存區(qū)緩存;
private:只能針對個人用戶,而不能被代理服務(wù)器緩存;
no-cache:強制客戶端直接向服務(wù)器發(fā)送請求,也就是說每次請求都必須向服務(wù)器發(fā)送。服務(wù)器接收到請求,判斷資源是否變更,是則返回新內(nèi)容,否則返回304。
no-store:禁止一切緩存(這個是響應(yīng)不被緩存的意思)
If-None-Match:第一次發(fā)送etag字段響應(yīng)給客戶端后,下次請求客戶端會同時發(fā)送一個If-None-Match來判斷數(shù)據(jù)是否發(fā)送變化,而它的值就是Etag的值
以Web瀏覽器使用 e-tag 為例,如下圖所示。
在配置了 Last-Modified/ETag 的情況下,瀏覽器再次訪問統(tǒng)一URI的資源時,還是會發(fā)送請求到服務(wù)器詢問文件是否已經(jīng)修改,如果沒有,服務(wù)器會生成304-Not Modified應(yīng)答和一個空的響應(yīng)體給瀏覽器,瀏覽器則直接從本地緩存取數(shù)據(jù);如果數(shù)據(jù)有變化,就將整個數(shù)據(jù)重新發(fā)給瀏覽器。
匯總
Last-Modified/ETag 與 Cache-Control/Expires的作用是不一樣的。前者是每次詢問實體版本是否有變化,后者是直接檢查本地的緩存還在有效的時間范圍內(nèi),如果在就不會發(fā)送任何請求。
- 兩者一起使用時,Cache-Control/Expires的優(yōu)先級要高于Last-Modified/ETag。
當(dāng)本地副本根據(jù) Cache-Control/Expires 判斷是否還在有效期內(nèi),如果不在,則會再次發(fā)送請求去服務(wù)器詢問修改時間(Last-Modified)或?qū)嶓w標(biāo)識(e-tag)。
Cache-Control與Expires的功能一致,都是指當(dāng)前資源的有效期,控制瀏覽器是直接從瀏覽器緩存取數(shù)據(jù)還是重新發(fā)請求到服務(wù)器取數(shù)據(jù)。只不過Cache-Control的選擇更多,設(shè)置更細(xì)致,如果同時設(shè)置的話,其優(yōu)先級高于Expires。
一般情況下,使用 Cache-Control/Expires 會配合 Last-Modified/ETag 一起使用,因為即使服務(wù)器設(shè)置緩存時間,當(dāng)用戶點擊 刷新 按鈕時,瀏覽器會忽略緩存繼續(xù)向服務(wù)器發(fā)送請求,這時Last-Modified/ETag將能夠很好利用服務(wù)端的返回碼304,從而減少響應(yīng)開銷。
通過在HTML頁面的節(jié)點中加入meta標(biāo)簽,可告訴瀏覽器當(dāng)前頁面不被緩存,每次訪問都需要去服務(wù)器拉取。代碼如下:
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
只不過,只有部分瀏覽器才支持這一用法,而且一般 緩存代理服務(wù)器都不支持,因為代理本身不解析 HTML 的內(nèi)容。瀏覽器緩存能夠極大地提升終端用戶的體驗,那么,用戶在使用瀏覽器的時候,會有各種操作,如輸入地址后回車、按F5刷新等等,這些行為對緩存的影響如下所示。
APP端緩存
盡管混合編程(hybrid programming)已成為時尚,吵在尖端,但移動互聯(lián)網(wǎng)目前還是原生應(yīng)用(APP)的天下。無論大小型APP,靈活的緩存不僅大大減輕了服務(wù)器的壓力,而且會因更快速的用戶體驗而方便用戶。** 如何把APP 緩存對于業(yè)務(wù)組件透明,以及APP緩存數(shù)據(jù)的及時更新**,是APP緩存能否成功應(yīng)用起來的關(guān)鍵。
組件透明是什么?
即組件對調(diào)用者來說沒有什么影響,也不需要維護(hù)。開箱即用。
APP緩存可使用那些緩存?
APP可以將內(nèi)容緩存在 內(nèi)存、文件或本地數(shù)據(jù)庫(例如SQLite)中,但基于 內(nèi)存的緩存 要謹(jǐn)慎使用。
本地庫操作
APP使用數(shù)據(jù)庫緩存的方法:
- 在下載完數(shù)據(jù)文件后,把文件的相關(guān)信息(如URL、路徑、下載時間、過期時間等)存放到數(shù)據(jù)庫.
- 等下次請求下載的時候,根據(jù)URL先從數(shù)據(jù)庫中查詢,如果查詢到當(dāng)前時間并未過期,就根據(jù)路徑讀取本地文件,實現(xiàn)緩存的效果。
優(yōu)點:方法具有靈活存放文件的屬性,進(jìn)而提供了很大的擴展性,可以為其他的功能提供良好的支持。
缺點:信息存儲過多,存儲容量會降低。所以要根據(jù)業(yè)務(wù)選擇合適主要的信息存儲
注意數(shù)據(jù)庫緩存的清理機制 。
文件操作
對APP中的某些界面,可以采用文件緩存的方法。這種方法使用文件操作的相關(guān)API得到文件的最后修改時間,與當(dāng)前時間判斷是否過期,從而實現(xiàn)緩存效果。
但需要注意的是,不同類型文件的緩存時間不一樣。比如:
文件類型:
- 圖片文件的內(nèi)容是相對不變的,直到最終被清理掉,APP可以永遠(yuǎn)讀取緩存中的圖片內(nèi)容。
- 配置文件中的內(nèi)容是可能更新的,需要設(shè)置一個可接受的緩存時間。同時,不同環(huán)境下的緩存時間標(biāo)準(zhǔn)也是不一樣的。
網(wǎng)絡(luò)環(huán)境:
WiFi網(wǎng)絡(luò)環(huán)境下,緩存時間可以設(shè)置短一點,一是網(wǎng)速較快,二是不產(chǎn)生流量費。
移動數(shù)據(jù)流量環(huán)境下,緩存時間可以設(shè)置長一點,節(jié)省流量,而且用戶體驗也更好。
在iOS開發(fā)中,SDWebImage是一個很棒的圖片緩存框架,主要類組成的結(jié)構(gòu)如下所示。
SDWebImage 是個比較大的類庫,提供一個UIImageView的類以支持遠(yuǎn)程加載來自網(wǎng)絡(luò)的圖片,具有緩存管理、異步下載、同一個URL下載次數(shù)控制和優(yōu)化等特征。使用時,只需要在頭文件中引入#import"UIImageView+WebCache.h" 即可調(diào)用異步加載圖片方法:
(void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
URL是圖片的地址
- placeholderImage是網(wǎng)絡(luò)圖片在尚未加載成功時顯示的圖像
- SDWebImageOptions是相關(guān)選項。
默認(rèn)情況下,SDWebImage會忽略Header中的緩存設(shè)置,將圖片以URL為key進(jìn)行保存,URL與圖片是一一映射關(guān)系。在APP請求同一個URL時,SDWebImage會從緩存中取得圖片。將第三個參數(shù)設(shè)置為SDWebImageRefreshCached就可以實現(xiàn)圖片更新操作,例如:
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中有兩種緩存
- 磁盤緩存
- 內(nèi)存緩存
框架都提供了相應(yīng)的清理方法:
[[[SDWebImageManager sharedManager] imageCache] clearDisk];
[[[SDWebImageManager sharedManager] imageCache] clearMemory];
要注意的是,在iOS7中,緩存機制做了修改,使用上述兩個方法只清除了SDWebImage的緩存,沒有清除系統(tǒng)的緩存,所以可以在清除緩存的代理中添加以下代碼:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
最后:
- 緩存根據(jù)存在方式有系統(tǒng)、硬件、軟件三類。
- 軟件根據(jù)場景客戶端、網(wǎng)絡(luò)、分布式緩存
- 用戶體驗:即用戶在使用一個產(chǎn)品或系統(tǒng)之前、使用期間和使用之后的全部感受。
- 系統(tǒng)性能指標(biāo)有響應(yīng)時間、延遲時間、吞吐量,并發(fā)用戶數(shù)和資源利用率等幾方面
- 網(wǎng)站架構(gòu)演講,經(jīng)歷起步、發(fā)展、中期、高手增長、后期
- 客戶端緩存分為頁面緩存、瀏覽器緩存、APP緩存