淺析互聯(lián)網(wǎng)中的緩存機(jī)制

7 評論 10818 瀏覽 162 收藏 13 分鐘

緩存,在互聯(lián)網(wǎng)產(chǎn)品中可以簡單理解為:第一次請求數(shù)據(jù)放到存儲器中,下次顯示該頁面先把上次保存的數(shù)據(jù)顯示出來,同時去請求數(shù)據(jù),請求完成刷新顯示新數(shù)據(jù),并將其再緩存起來。

當(dāng)今互聯(lián)網(wǎng)應(yīng)用(網(wǎng)站或App)的整體實現(xiàn)流程是:用戶的請求從界面(瀏覽器或App界面)到網(wǎng)絡(luò)傳送、應(yīng)用服務(wù)再到存儲(數(shù)據(jù)庫或文件系統(tǒng)),然后返回到界面呈現(xiàn)內(nèi)容。

隨著內(nèi)容信息越來越復(fù)雜,用戶數(shù)和訪問量越來越大,我們的應(yīng)用需要支撐更多的并發(fā)量,同時應(yīng)用服務(wù)器和數(shù)據(jù)庫服務(wù)器所做的計算也越來越多。但是往往我們的應(yīng)用服務(wù)器資源是有限的,數(shù)據(jù)庫每秒能接受的請求次數(shù)也是有限的(文件的讀寫也是有限的),如何能夠有效利用有限的資源來提供盡可能大的吞吐量?一個有效的辦法就是引入緩存,每個環(huán)節(jié)中請求可以從緩存中直接獲取目標(biāo)數(shù)據(jù)并返回,從而減少計算量,有效提升響應(yīng)速度,讓有限的資源服務(wù)更多的用戶。

計算機(jī)緩存

計算機(jī)的緩存往往使用的是RAM(斷電就掉的非永久儲存),所以在用完后還是會把文件送到硬盤等存儲器里永久存儲。計算機(jī)里最大的緩存是內(nèi)存條,最快的是CPU上鑲嵌的L1和L2緩存,顯卡的顯存是給顯卡運(yùn)算芯片用的緩存,硬盤上也有16M或者32M的緩存。

其工作原理是當(dāng)CPU要讀取數(shù)據(jù)時,首先從CPU緩存中查找,找到就立即讀取并送給CPU處理;如果沒有找到,就從速率相對較慢的內(nèi)存中讀取并送給CPU處理,同時把這個數(shù)據(jù)所在的數(shù)據(jù)區(qū)塊調(diào)入緩存中,可以使以后對整塊數(shù)據(jù)的讀取都從緩存中進(jìn)行,不必再調(diào)用內(nèi)存。這樣的讀取機(jī)制CPU讀取緩存的命中率非常高,也就是說CPU下一次要讀取的數(shù)據(jù)90%都在CPU緩存中,只有大約10%需要從內(nèi)存讀取。這大大節(jié)省了CPU直接讀取內(nèi)存的時間,也使CPU讀取數(shù)據(jù)時基本無需等待。

WEB瀏覽器緩存

下面我們進(jìn)入正題。

瀏覽器會緩存它瀏覽過的「資源」(包括網(wǎng)頁,圖片等),如果資源在保質(zhì)期內(nèi),那下次同樣的請求直接用緩存。過期之后,會帶上資源上次的修改時間,由服務(wù)器來判斷是否失效,失效的話就會給瀏覽器返回新的數(shù)據(jù)并繼續(xù)緩存下來。

瀏覽器的緩存,存在用戶電腦的硬盤上,用戶每次使用瀏覽器讀取緩存時先將硬盤上的緩存數(shù)據(jù)加載到內(nèi)存中,再讀取給瀏覽器。

瀏覽器端緩存的規(guī)則主要在HTTP協(xié)議頭和HTML的meta標(biāo)簽中定義。他們分別從新鮮度和校驗值兩個維度來規(guī)定瀏覽器是直接使用緩存中的數(shù)據(jù),還是需要去源服務(wù)器獲取更新的版本。

新鮮度(過期機(jī)制):緩存數(shù)據(jù)保質(zhì)期。緩存數(shù)據(jù)必須滿足以下條件,瀏覽器會認(rèn)為它是有效的,足夠新的:

  • 含有完整的過期時間控制頭信息(HTTP協(xié)議報文頭),并且仍在有效期內(nèi)
  • 瀏覽器已經(jīng)使用過這個緩存數(shù)據(jù),并且在上一次會話中(也就是用戶上一次訪問該數(shù)據(jù)時)已經(jīng)檢查過其新鮮度

滿足以上兩個情況的一種,瀏覽器會直接從緩存中獲取緩存數(shù)據(jù)并渲染給瀏覽器。

校驗值(驗證機(jī)制):服務(wù)器返回數(shù)據(jù)的時候有時在頭信息中帶上這個資源的實體標(biāo)簽,它可以用來作為瀏覽器再次請求過程的校驗標(biāo)識。如過發(fā)現(xiàn)校驗標(biāo)識不匹配,說明數(shù)據(jù)已經(jīng)被修改或過期,瀏覽器需要重新獲取數(shù)據(jù)內(nèi)容。

HTTP緩存機(jī)制

還記得HTTP協(xié)議嗎?在這篇文章中有對HTTP協(xié)議的簡單介紹:淺析前后端數(shù)據(jù)交互

當(dāng)用戶通過瀏覽器發(fā)起一個數(shù)據(jù)請求的時候,瀏覽器會通過以下幾步來獲取數(shù)據(jù):

  • 本地緩存階段:先在本地查找該數(shù)據(jù),如果有發(fā)現(xiàn)該數(shù)據(jù),而且該數(shù)據(jù)還沒有過期,就使用此數(shù)據(jù),不會發(fā)送http請求到服務(wù)器
  • 協(xié)商緩存階段:如果在本地緩存找到對應(yīng)的數(shù)據(jù),但是不知道該數(shù)據(jù)是否過期,則發(fā)一個HTTP請求到服務(wù)器,然后服務(wù)器判斷這個請求,如果請求的數(shù)據(jù)在服務(wù)器上沒有改動過或過期,則返回304狀態(tài)碼(可以理解為服務(wù)器給瀏覽器的暗號),讓瀏覽器在本地找到該數(shù)據(jù)
  • 緩存失敗階段:當(dāng)服務(wù)器發(fā)現(xiàn)請求的資源已經(jīng)修改過,或者這是一個新的請求,服務(wù)器則返回該數(shù)據(jù),并且返回200狀態(tài)碼, 此過程的前提是指找到該數(shù)據(jù),如果服務(wù)器上沒有數(shù)據(jù),則返回404(這個大家多見過吧,就是平時見到404頁面時的狀態(tài)碼)

瀏覽器中的操作對緩存的影響

  • 強(qiáng)制刷新:當(dāng)按下ctrl+F5來刷新頁面的時候,瀏覽器將繞過各種緩存(本地緩存和協(xié)商緩存), 直接讓服務(wù)器返回最新數(shù)據(jù)
  • 普通刷新:當(dāng)按下F5或者點(diǎn)擊刷新按鈕來刷新頁面的時候,瀏覽器將繞過本地緩存發(fā)送請求給服務(wù)器,此時協(xié)商緩存是有效的
  • 回車或跳轉(zhuǎn):當(dāng)在地址欄上輸入回車或者按下跳轉(zhuǎn)按鈕的時候,所有緩存都生效

瀏覽器緩存機(jī)制

安卓、iOS緩存機(jī)制

APP上的緩存機(jī)制和瀏覽器緩存的原理類似,APP與服務(wù)器交互的協(xié)議同樣是大多基于HTTP(S)。

先普及下基礎(chǔ)知識:手機(jī)內(nèi)存包括運(yùn)行內(nèi)存和內(nèi)部存儲。運(yùn)行內(nèi)存是用來運(yùn)行程序的,不能用來永久存儲數(shù)據(jù),手機(jī)一旦關(guān)機(jī)或殺死進(jìn)程,在內(nèi)存中的所有數(shù)據(jù)都將會丟失。內(nèi)部存儲相當(dāng)于計算機(jī)中的硬盤的角色,用于存儲操作系統(tǒng)和應(yīng)用程序的存儲介質(zhì)。

iOS的本地緩存數(shù)據(jù)存在磁盤存儲(內(nèi)部存儲)中,由于Android手機(jī)通常將內(nèi)部存儲器固定在芯上,所以一般無法更換內(nèi)部存儲器的。 為了增強(qiáng)Android手機(jī)的存儲能力,很多Android手機(jī)都支持?jǐn)U展的SD卡(相當(dāng)于計算機(jī)的U盤或者移動硬盤)功能。所以,Android手機(jī)存儲緩存是可以選擇數(shù)據(jù)存儲位置的。

APP端存儲數(shù)據(jù)的時候,會存儲很多字段內(nèi)容,一般情況下后臺會給每條數(shù)據(jù)設(shè)定一個獨(dú)立的id值,那么前端在請求數(shù)據(jù)的可以先查詢本地緩存的數(shù)據(jù)中,最新的一條數(shù)據(jù)的id值,通過網(wǎng)絡(luò)請求,把這個id值發(fā)給服務(wù)端,服務(wù)端會根據(jù)這個id在后臺服務(wù)器中查詢是否有比這個id值更大(更新)的數(shù)據(jù)存在,如果有就把新的數(shù)據(jù)返回給前端APP。

數(shù)據(jù)庫緩存

數(shù)據(jù)庫的緩存機(jī)制分為兩個層面。

  1. 由數(shù)據(jù)庫提供,可以對數(shù)據(jù)表建立的高速緩存。數(shù)據(jù)庫的數(shù)據(jù)臨時保存在一個位置上,再次同樣的請求直接把這個數(shù)據(jù)返回去,而不需要再次去查詢各種表取數(shù)據(jù)了,減少了查數(shù)據(jù)庫的時間,提升效率。并不是所有的歷史記錄都緩存起來,要有策略,比如只緩存兩個月的數(shù)據(jù),并且兩個月之前有請求過之后不再請求該數(shù)據(jù)的時候就會回收,就是把這條記錄抹掉,就近多次請求的才會保存。時間過長、使用率不高的優(yōu)先清除,要不然緩存太多就失去了緩存的本質(zhì)和意義。
  2. 在數(shù)據(jù)庫中,數(shù)據(jù)都是存放在磁盤中的。雖然數(shù)據(jù)庫層做了對應(yīng)的緩存,但這種數(shù)據(jù)庫層次的緩存一般針對的是查詢內(nèi)容,一般只有表中數(shù)據(jù)沒有變更的時候,數(shù)據(jù)庫對應(yīng)的緩存才發(fā)揮了作用。有時并不能減少業(yè)務(wù)系統(tǒng)對數(shù)據(jù)庫產(chǎn)生的增、刪、查、改產(chǎn)生的龐大壓力。此時,一般的做法是在數(shù)據(jù)庫與業(yè)務(wù)服務(wù)器之間增加一個緩存服務(wù)器,比如我們熟悉的redis。客戶端第一次請求的數(shù)據(jù)從數(shù)據(jù)庫拿出后就放到了redis中,數(shù)據(jù)不過期或不更改的前提下,下一次的請求都從redis中直接拿數(shù)據(jù),這樣做極大的緩解了數(shù)據(jù)庫的壓力。

服務(wù)器緩存

業(yè)務(wù)服務(wù)器緩存

業(yè)務(wù)服務(wù)器緩存是將動態(tài)頁面直接生成靜態(tài)的頁面放在服務(wù)器上的硬盤里,用戶調(diào)取相同頁面時,靜態(tài)頁面將直接下載到客戶端,不再需要通過程序的運(yùn)行和數(shù)據(jù)庫的訪問,大大節(jié)約了服務(wù)器的負(fù)載。

每次訪問頁面時,會檢測相應(yīng)的緩存頁面是否存在,若不存在,則連接數(shù)據(jù)庫得到數(shù)據(jù)渲染頁面并生成緩存頁面文件,這樣下次訪問的頁面文件就能發(fā)揮作用了。

舉一個小例子:

用戶A訪問a頁面,服務(wù)器解析a頁面返回給用戶A,同時在服務(wù)器內(nèi)存上做一個映射,把a(bǔ)頁面緩存在服務(wù)器的硬盤上。用戶B訪問a頁面,服務(wù)器直接根據(jù)內(nèi)存上的映射找到相應(yīng)的頁面緩存,直接返回給用戶B。這樣做減少了服務(wù)器對同以頁面的重復(fù)解析。

代理服務(wù)器緩存

代理服務(wù)器是客戶端和業(yè)務(wù)服務(wù)器之間的中間服務(wù)器,客戶端先向這個中間服務(wù)器發(fā)起請求,經(jīng)過處理后,再將請求轉(zhuǎn)發(fā)到業(yè)務(wù)服務(wù)器。代理服務(wù)器緩存的運(yùn)作原理跟瀏覽器的運(yùn)作原理差不多,只是規(guī)模更大。可以把它理解為一個共享緩存,不只為一個用戶服務(wù),一般為大量用戶提供服務(wù),因此在減少相應(yīng)時間和帶寬使用方面很有效,同一個緩存數(shù)據(jù)會被重復(fù)使用多次。

以上,就是關(guān)于緩存機(jī)制的簡單總結(jié)。產(chǎn)品汪們,再涉及項目中的緩存機(jī)制時,就不怕被程序猿們懟了!

 

作者:流年,互聯(lián)網(wǎng)產(chǎn)品設(shè)計師,4年互聯(lián)網(wǎng)產(chǎn)品設(shè)計經(jīng)驗。

本文由 @流年 原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載。

題圖由作者提供

更多精彩內(nèi)容,請關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號或下載App
評論
評論請登錄
  1. 講的非常好,很有用

    來自上海 回復(fù)
  2. 太棒了,十分清晰易懂

    來自廣東 回復(fù)
  3. 太棒了!獲益匪淺!666!

    來自河南 回復(fù)
  4. 講的不錯

    回復(fù)
  5. nice!講的清晰,易懂!

    來自上海 回復(fù)
  6. 來自廣東 回復(fù)
  7. get it!thank you

    來自四川 回復(fù)