緩存,在互聯網産品中可以簡單理解為:第一次請求數據放到存儲器中,下次顯示該頁面先把上次保存的數據顯示出來,同時去請求數據,請求完成刷新顯示新數據,并将其再緩存起來。
當今互聯網應用(網站或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年互聯網産品設計經驗。
本文由 @流年 原創發布于人人都是産品經理。未經許可,禁止轉載。
題圖由作者提供
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!