查詢怎么測試緩存時,發現的非常棒的文章。http://www.51ste.com/share/det-762-1.html
以下為原文:
什么是緩存?
緩存是我們在生活中經常聽到一個詞,如 怎么清理瀏覽器的緩存, 手機空間不夠了,得刪除緩存, 硬盤的緩存是不是越大越好等等的問題;
其實這些 緩存可以分成3種:
- 一種指硬件上的,像硬盤緩存和CPU緩存;
- 一種客戶端緩存;
- 一種是指服務端緩存;
后兩種更像是一種技術或者是服務;
- 硬件緩存:指的是一塊芯片,可以被集成到硬盤或者是CPU上。它的作用就是充當硬盤(CPU)與外界接口(通常是內存)之間的暫存器,利用緩存可以減輕系統的負荷,同時提高數據的傳輸速率;
- 客戶端緩存:某些應用,如瀏覽器,X寶,X信等,為了實現能夠快速響應用戶的請求,會把用戶之前瀏覽的東西(如圖片等)存在本地;在下次訪問時,如果本地的緩存里有請求的內容,那么就直接展示出來,不用再次向服務器請求;
- 服務端緩存:它與客戶端緩存目的相同,只不過是站在服務器這邊考慮的;如果每次接到客戶端請求都要連接一次數據庫,當用戶請求多的時候,負載過大;這時可以把一些經常被請求的數據存放在內存中,當有請求時直接返回,不用經過數據庫,這樣就可以減輕數據庫的負擔;
小結
緩存是臨時存放數據(使用頻繁的數據)的地方,介於外部請求和真實數據之間;
為什么要用緩存
從一個用戶的角度來看,體驗最好的肯定是不管什么情況下,都能成功訪問這個頁面,並且打開的速度很快,也就是保證正常工作的前提下時間盡可能短;
如果沒有緩存,我們的體驗可能是這樣的:
用戶請求一個數據,這個數據得從數據庫中去取,隨着用戶越來越多和數據量越來越大,每次用戶請求的時間就會越來越長,而且數據庫無時不刻都在工作;
這樣用戶和數據庫都很痛苦,時間一長,就有可能發生下面兩件事情:
1)用戶很煩,抱怨頁面加載太慢或者打不開,最后放棄了這個應用;
2)數據庫滿負荷工作,偶爾崩潰(導致頁面錯誤);
分析原因:由於數據庫的連接數和連接時長是有限制的,但請求過多,超出了數據庫能承受的范圍,導致數據庫崩潰;
那為什么不把一部分數據放在別的地方,這樣有用戶請求這些數據時,就不用從數據庫中取了?
服務器緩存
工作原理
當客戶端向服務器請求一個資源時,服務器首先在緩存中找,如果在緩存中,那么直接返回,不需要連接數據庫;
如果請求的資源不在緩存中,這時再去數據庫中找,找到后返回給客戶端,並將這個資源加入緩存中;
這樣下次請求相同資源時,就不需要連接數據庫了。而且如果把緩存放在內存中,因為對內存的操作要比對數據庫操作快得多,這樣請求時間也會縮短;
所以,通過使用緩存,就可以保證滿足用戶的需求,在正常工作的前提下響應時間盡可能短;
特別需要注意緩存失效的場景,如:
- 數據庫的數據已經更新了,那對應的緩存數據也要更新;
- 緩存超過失效時間,需要重新發起請求來更新緩存;
- 緩存滿了,比如緩存滿了,重新發起請求,新的資源重新加入緩存,一般做法是把緩存里最舊的資源剔除,加入新的資源;
前端緩存
類型
緩存分為兩類:強制緩存和協商緩存,定義如下:
- 強制緩存:客戶端直接從緩存中讀取數據,不與服務器作交互;
- 協商緩存:客戶端發送特定的報文到服務器,服務器根據接收到的報文判斷資源是否有更新,有則返回200和最新的資源文件,無則返回304使客戶端從緩存中讀取數據;
緩存由什么決定?
緩存由http報文的內容決定,關系如下:
max-age或者 expires都決定了緩存的過期時間,會使客戶端再次請求數據時先判斷緩存是否過期,未過期則直接從緩存中讀取數據(強制緩存);
兩者的區別是前者是個相對值,相對於客戶端的時間,后者直接定義了截止時間,且相對於服務端的時間;
協商緩存由 Last-Modified、 If-Modified-Since 或 ETag、 If-None-Match兩組報文決定;
字段的意思分別如下:
- Last-Modified:表示服務器上某文件最近的修改時間,存在於響應報文;
- If-Modified-Since:值等於 Last-Modified,存在於請求報文,用於將 Last-Modified值返回給服務端作比較;
緩存的總體過程
首次請求資源:
非首次請求資源:
在第一次請求資源后,瀏覽器會將資源連同響應報文一起緩存到本地,其中響應報文可能包含了關於緩存的頭信息;
因而后續請求的時候,瀏覽器可以根據本地緩存的頭信息知道資源的緩存決策,判斷是否強制緩存,或者移交服務器判斷是否協商緩存;
緩存穿透、緩存擊穿、緩存雪崩
在服務器緩存里面,有3個特殊的名詞:緩存穿透、緩存擊穿、緩存雪崩;
這3個到底是什么?
緩存穿透
正常情況下,查詢的數據都存在,如果請求一個不存在的數據,也就是緩存和數據庫都查不到這個數據,每次都會去數據庫查詢,這種查詢不存在數據的現象稱為緩存穿透;
穿透帶來的問題
如果每次都拿一個不存在的id去查詢數據庫,可能會導致你的數據庫壓力增大;
如何發現緩存穿透
- 業務的響應時間:可以借助ELK或其他監控系統,對業務的接口進行檢測,原本緩存就是響應時間比較快的,如果經常超過閾值就一定會有所體現;
- 總調用數、cache層命中數、storage層命中數;
解決辦法--緩存空值
之所以發生穿透,是因為緩存中沒有存儲這些數據的key,從而每次都查詢數據庫;
可以為這些key在緩存中設置對應的值為null,后面查詢這個key的時候就不用查詢數據庫了;
當然為了健壯性,我們要對這些key設置過期時間,以防止真的有數據;
緩存擊穿
在高並發的情況下,大量的請求同時查詢同一個key時,此時這個key正好失效了或者不存在,就會導致同一時間,這些請求都會去查詢數據庫,這樣的現象稱為緩存擊穿;
比如請求一些特殊字符,就會出現該情況;
引起的原因
- 代碼問題,比如保存到緩存時用的是固定值;
- 惡意攻擊,比如爬蟲,在請求時傳一些不正常的值;
帶來的問題
會造成某一時刻數據庫請求量過大;
解決辦法
采用分布式鎖,只有拿到鎖的第一個線程去請求數據庫,然后插入緩存,若其它線程獲取鎖失敗,則等待一段時間后重試;
緩存雪崩
當某一時刻發生大規模的緩存失效的情況,比如緩存服務宕機了;
解決方法
跟緩存穿透一樣加鎖排隊;
建立備份緩存,緩存A和緩存B,A設置超時時間,B不設置超時時間,先從A讀緩存,A沒有則讀B,並且更新A和B的緩存;
解決熱點數據集中失效問題
在設置緩存的時候,一般會給緩存設置一個失效時間,過了這個時間,緩存就失效了;
對於一些熱點的數據來說,當緩存失效以后會存在大量的請求過來,然后打到數據庫去,從而可能導致數據庫崩潰的情況;
解決辦法
- 設置不同的失效時間;
- 采用緩存擊穿的解決辦法,加鎖;
- 永不失效,就是采用定時任務對快要失效的緩存進行更新緩存和失效時間;
緩存的測試點
功能:
- 緩存是否可以正確被創建,包括位置、名字和內容;
- 緩存是否被清除,包括主動清楚以及被第三方發起的清除,清除后是否正常工作及清除失效的情況;
- 系統運行過程中,redis緩存數據生效、緩存的數據讀取正確、數據寫入落地正確,數據有效期設置合理;
- 緩存與數據庫的數據一致性檢測;
- DB事務性導致回滾,緩存是否回滾,有沒有產生臟數據;
- 緩存是否有大小限制,達到大小臨界值如何處理;
- 緩存時突然被中斷,如何處理;
- 緩存失效后,是否能正常表現;
自動化:
- 自動化用例中斷言部分設計緩存層斷言並且自動化框架本身對於斷層層次可配置;
性能及穩定性:
- 關注業務本身應用場景及緩存結構,是否使用緩存;
- 預防緩存穿透、緩存雪崩、緩存擊穿引發的系統風險;
擴容:
- 關注擴容方案設計、老數據備份策略、回滾方案;
- 關注擴容后分片策略的變化;
- 擴容后熱點數據失效率或命中率以及對后端DB帶來的壓力;
環境:
無網絡&有數據:
- 緩存大小未超過,緩存時間有效期內,顯示緩存數據加載;
- 緩存大小超過,本地緩存數據刪除,顯示無網提示,無數據加載;
- 緩存時間過期,本地緩存數據刪除,顯示無網提示,無數據加載;
無網絡&無數據:
- 顯示無數據加載;
有網絡&有數據:
- 緩存大小未超過,緩存時間有校內,顯示緩存數據加載;
- 緩存大小超過了,本地緩存數據刪除,直接從線上拉取數據;
- 緩存時間過期,本地緩存數據刪除,直接從線上拉取數據;
有網絡&無數據:
- 直接從線上拉取數據存到本地;
緩存存儲:
- 客戶端安裝后,有網絡,開始存儲數據到本地;
- 覆蓋安裝,緩存數據依然存儲在本地;
- 清除數據、卸載、重裝,內存和本地緩存數據清零;
異常情況:
- 由於網絡原因緩存失敗,則無法讀取緩存數據;
- 由於服務器原因導致緩存失敗,則無法取緩存數據;
- 終端本地的數據接近滿值,內存被占用,無法讀取緩存數據;
- 設置的緩存文件夾和數據文件不可讀寫;
- 緩存的刷新機制是否手動操作;