淺析互聯網中的緩存機制
緩存,在互聯網產品中可以簡單理解為:第一次請求數據放到存儲器中,下次顯示該頁面先把上次保存的數據顯示出來,同時去請求數據,請求完成刷新顯示新數據,并將其再緩存起來。
當今互聯網應用(網站或App)的整體實現流程是:用戶的請求從界面(瀏覽器或App界面)到網絡傳送、應用服務再到存儲(數據庫或文件系統),然后返回到界面呈現內容。
隨著內容信息越來越復雜,用戶數和訪問量越來越大,我們的應用需要支撐更多的并發量,同時應用服務器和數據庫服務器所做的計算也越來越多。但是往往我們的應用服務器資源是有限的,數據庫每秒能接受的請求次數也是有限的(文件的讀寫也是有限的),如何能夠有效利用有限的資源來提供盡可能大的吞吐量?一個有效的辦法就是引入緩存,每個環節中請求可以從緩存中直接獲取目標數據并返回,從而減少計算量,有效提升響應速度,讓有限的資源服務更多的用戶。
計算機緩存
計算機的緩存往往使用的是RAM(斷電就掉的非永久儲存),所以在用完后還是會把文件送到硬盤等存儲器里永久存儲。計算機里最大的緩存是內存條,最快的是CPU上鑲嵌的L1和L2緩存,顯卡的顯存是給顯卡運算芯片用的緩存,硬盤上也有16M或者32M的緩存。
其工作原理是當CPU要讀取數據時,首先從CPU緩存中查找,找到就立即讀取并送給CPU處理;如果沒有找到,就從速率相對較慢的內存中讀取并送給CPU處理,同時把這個數據所在的數據區塊調入緩存中,可以使以后對整塊數據的讀取都從緩存中進行,不必再調用內存。這樣的讀取機制CPU讀取緩存的命中率非常高,也就是說CPU下一次要讀取的數據90%都在CPU緩存中,只有大約10%需要從內存讀取。這大大節省了CPU直接讀取內存的時間,也使CPU讀取數據時基本無需等待。
WEB瀏覽器緩存
下面我們進入正題。
瀏覽器會緩存它瀏覽過的「資源」(包括網頁,圖片等),如果資源在保質期內,那下次同樣的請求直接用緩存。過期之后,會帶上資源上次的修改時間,由服務器來判斷是否失效,失效的話就會給瀏覽器返回新的數據并繼續緩存下來。
瀏覽器的緩存,存在用戶電腦的硬盤上,用戶每次使用瀏覽器讀取緩存時先將硬盤上的緩存數據加載到內存中,再讀取給瀏覽器。
瀏覽器端緩存的規則主要在HTTP協議頭和HTML的meta標簽中定義。他們分別從新鮮度和校驗值兩個維度來規定瀏覽器是直接使用緩存中的數據,還是需要去源服務器獲取更新的版本。
新鮮度(過期機制):緩存數據保質期。緩存數據必須滿足以下條件,瀏覽器會認為它是有效的,足夠新的:
- 含有完整的過期時間控制頭信息(HTTP協議報文頭),并且仍在有效期內
- 瀏覽器已經使用過這個緩存數據,并且在上一次會話中(也就是用戶上一次訪問該數據時)已經檢查過其新鮮度
滿足以上兩個情況的一種,瀏覽器會直接從緩存中獲取緩存數據并渲染給瀏覽器。
校驗值(驗證機制):服務器返回數據的時候有時在頭信息中帶上這個資源的實體標簽,它可以用來作為瀏覽器再次請求過程的校驗標識。如過發現校驗標識不匹配,說明數據已經被修改或過期,瀏覽器需要重新獲取數據內容。
HTTP緩存機制
還記得HTTP協議嗎?在這篇文章中有對HTTP協議的簡單介紹:淺析前后端數據交互
當用戶通過瀏覽器發起一個數據請求的時候,瀏覽器會通過以下幾步來獲取數據:
- 本地緩存階段:先在本地查找該數據,如果有發現該數據,而且該數據還沒有過期,就使用此數據,不會發送http請求到服務器
- 協商緩存階段:如果在本地緩存找到對應的數據,但是不知道該數據是否過期,則發一個HTTP請求到服務器,然后服務器判斷這個請求,如果請求的數據在服務器上沒有改動過或過期,則返回304狀態碼(可以理解為服務器給瀏覽器的暗號),讓瀏覽器在本地找到該數據
- 緩存失敗階段:當服務器發現請求的資源已經修改過,或者這是一個新的請求,服務器則返回該數據,并且返回200狀態碼, 此過程的前提是指找到該數據,如果服務器上沒有數據,則返回404(這個大家多見過吧,就是平時見到404頁面時的狀態碼)
瀏覽器中的操作對緩存的影響
- 強制刷新:當按下ctrl+F5來刷新頁面的時候,瀏覽器將繞過各種緩存(本地緩存和協商緩存), 直接讓服務器返回最新數據
- 普通刷新:當按下F5或者點擊刷新按鈕來刷新頁面的時候,瀏覽器將繞過本地緩存發送請求給服務器,此時協商緩存是有效的
- 回車或跳轉:當在地址欄上輸入回車或者按下跳轉按鈕的時候,所有緩存都生效
瀏覽器緩存機制
安卓、iOS緩存機制
APP上的緩存機制和瀏覽器緩存的原理類似,APP與服務器交互的協議同樣是大多基于HTTP(S)。
先普及下基礎知識:手機內存包括運行內存和內部存儲。運行內存是用來運行程序的,不能用來永久存儲數據,手機一旦關機或殺死進程,在內存中的所有數據都將會丟失。內部存儲相當于計算機中的硬盤的角色,用于存儲操作系統和應用程序的存儲介質。
iOS的本地緩存數據存在磁盤存儲(內部存儲)中,由于Android手機通常將內部存儲器固定在芯上,所以一般無法更換內部存儲器的。 為了增強Android手機的存儲能力,很多Android手機都支持擴展的SD卡(相當于計算機的U盤或者移動硬盤)功能。所以,Android手機存儲緩存是可以選擇數據存儲位置的。
APP端存儲數據的時候,會存儲很多字段內容,一般情況下后臺會給每條數據設定一個獨立的id值,那么前端在請求數據的可以先查詢本地緩存的數據中,最新的一條數據的id值,通過網絡請求,把這個id值發給服務端,服務端會根據這個id在后臺服務器中查詢是否有比這個id值更大(更新)的數據存在,如果有就把新的數據返回給前端APP。
數據庫緩存
數據庫的緩存機制分為兩個層面。
- 由數據庫提供,可以對數據表建立的高速緩存。數據庫的數據臨時保存在一個位置上,再次同樣的請求直接把這個數據返回去,而不需要再次去查詢各種表取數據了,減少了查數據庫的時間,提升效率。并不是所有的歷史記錄都緩存起來,要有策略,比如只緩存兩個月的數據,并且兩個月之前有請求過之后不再請求該數據的時候就會回收,就是把這條記錄抹掉,就近多次請求的才會保存。時間過長、使用率不高的優先清除,要不然緩存太多就失去了緩存的本質和意義。
- 在數據庫中,數據都是存放在磁盤中的。雖然數據庫層做了對應的緩存,但這種數據庫層次的緩存一般針對的是查詢內容,一般只有表中數據沒有變更的時候,數據庫對應的緩存才發揮了作用。有時并不能減少業務系統對數據庫產生的增、刪、查、改產生的龐大壓力。此時,一般的做法是在數據庫與業務服務器之間增加一個緩存服務器,比如我們熟悉的redis。客戶端第一次請求的數據從數據庫拿出后就放到了redis中,數據不過期或不更改的前提下,下一次的請求都從redis中直接拿數據,這樣做極大的緩解了數據庫的壓力。
服務器緩存
業務服務器緩存
業務服務器緩存是將動態頁面直接生成靜態的頁面放在服務器上的硬盤里,用戶調取相同頁面時,靜態頁面將直接下載到客戶端,不再需要通過程序的運行和數據庫的訪問,大大節約了服務器的負載。
每次訪問頁面時,會檢測相應的緩存頁面是否存在,若不存在,則連接數據庫得到數據渲染頁面并生成緩存頁面文件,這樣下次訪問的頁面文件就能發揮作用了。
舉一個小例子:
用戶A訪問a頁面,服務器解析a頁面返回給用戶A,同時在服務器內存上做一個映射,把a頁面緩存在服務器的硬盤上。用戶B訪問a頁面,服務器直接根據內存上的映射找到相應的頁面緩存,直接返回給用戶B。這樣做減少了服務器對同以頁面的重復解析。
代理服務器緩存
代理服務器是客戶端和業務服務器之間的中間服務器,客戶端先向這個中間服務器發起請求,經過處理后,再將請求轉發到業務服務器。代理服務器緩存的運作原理跟瀏覽器的運作原理差不多,只是規模更大??梢园阉斫鉃橐粋€共享緩存,不只為一個用戶服務,一般為大量用戶提供服務,因此在減少相應時間和帶寬使用方面很有效,同一個緩存數據會被重復使用多次。
以上,就是關于緩存機制的簡單總結。產品汪們,再涉及項目中的緩存機制時,就不怕被程序猿們懟了!
作者:流年,互聯網產品設計師,4年互聯網產品設計經驗。
本文由 @流年 原創發布于人人都是產品經理。未經許可,禁止轉載。
題圖由作者提供
講的非常好,很有用
太棒了,十分清晰易懂
太棒了!獲益匪淺!666!
講的不錯
nice!講的清晰,易懂!
贊
get it!thank you