【金三銀四】快取面試題-web層快取
由于快取的種類眾多,不同場景的快取也存在著一些不一樣的特點,內容太多,本文僅限于Web應用層快取
什么是快取,為什么要用快取?
速度問題
由于記憶體的讀寫速度要比磁盤的讀寫速度快一個數量級,
一般的ddr3代1333的速度讀寫在7000mb/s以上,
ssd硬碟讀寫大概500mb/s
如果是機械硬碟,或者其他存盤設備,那讀寫速度可能會更低,
連接問題
假如公司網站首頁有個介面,需要去資料庫獲取一些資訊,(別和栗子較真)格式如下:
curl http://xxx.cn/homeInfo
#回傳值
{
"pageName": "home",
"title": "XXXX",
"website": "http://www.xxxx.com/",
"companyName": "xxxx",
"employees": "103699人",
"desc": "XXXX網路技術有限公司(簡稱:XXXX集團或XXXX)是以曾擔任英語教師的馬某為首的18人于1999年在浙江省杭州市創立的公司"
}
比如現在客戶端有100萬個用戶打開了一個網站的,那么就會有100萬個請求去讀資料庫,
這里會發現一個問題,就是我100萬個人明明獲取的資料都是同一份資料,但是我資料庫要查100萬次,
先不說資料庫能不能抗的住這100萬的請求,會發現這操作就很重復,很冗余,很低效,
基于上面兩個問題,那么快取就能很好的解決這兩個問題,
快取的主要任務就是為了減少資料庫(硬碟)的讀寫次數,
沒有快取得請求方式

加了快取的請求方式

快取的流程
請求到Java時,Java先從Redis中讀取資料,如果讀取到資料直接回傳給前端,
如果讀取不到則從資料庫中讀取,存入Redis中,并回傳,當下次讀取時redis就已經有資料了,不會再直接訪問資料庫了,
快取資料一致性問題
資料庫中的資料快取在Redis之后,如果資料庫資料發生修改,那么從快取中讀到的資料就會不正確,
所以為了保證快取中的資料和資料庫的資料保持一致,我們通常的做法是,
在資料庫進行新增,修改,洗掉的時候,清楚redis中的快取,這樣當下次查詢的時候,會重新讀取資料庫再快取到Redis中,
快取的三大坑
快取穿透
- 快取穿透是指查詢的資料在資料庫是沒有的,那么在快取中自然也沒有,所以在快取中查不到就會去資料庫查詢,這樣的請求一多,我們資料庫的壓力自然會增大,
- 解決
對于回傳為 NULL 的依然快取,對于拋出例外的回傳不進行快取,注意不要把拋例外的也給快取了
制定一些規則過濾一些不可能存在的資料,小資料用 BitMap,大資料可以用布隆過濾器
快取擊穿
- 對于某些 Key 設定了過期時間,但是它是熱點資料,如果某個 Key 失效,可能大量的請求打過來,快取未命中,然后去資料庫訪問,此時資料庫訪問量會急劇增加
- 解決
加分布式鎖
異步加載,對這部分熱點資料采取到期自動重繪的策略
快取雪崩
- 快取雪崩是指快取不可用或者大量快取由于超時時間相同在同一時間段失效,大量請求直接訪問資料庫,資料庫壓力過大導致系統雪崩,
- 解決
增加快取系統可用性,通過監控關注快取的健康程度,根據業務量適當的擴容快取,
采用多級快取,不同級別快取設定的超時時間不同,即使某個級別快取都過期,也有其他級別快取兜底,
快取的 Key 值可以取個隨機值,比如以前是設定 10 分鐘的超時時間,那每個 Key 都可以隨機 8-13 分鐘過期,盡量讓不同 Key 的過期時間不同,
如圖,當Redis出現問題的時候,多個JVM行程將使用從Map中獲取快取的資料,而不至于直接訪問資料庫,

本地快取
本地快取可以簡單的使用map或者一些第三方工具
如Guava的Cache,Hutool的Cache等,
這些工具類也都是繼承了Map做了LRU快取,失效時間快取等功能,
其都是依賴于JVM行程的,
優點是:單個服務掛了,不會影響其他JVM行程,
缺點是:沒有序列化,重啟或者斷電快取資料丟失;
使用不恰當時,容易記憶體溢位;
總結
好的快取系統因該讓用戶體驗不到他的存在,而只享受它所帶來的速度提升,
所以快取一定要做好兼容,不要因為引入了快取,導致系統不可用,那是得不償失的,
選擇適合自己的快取方案,不一定所有的系統都需要快取,下面列舉一些簡單的web應用快取方案,
快取方案
無快取方式
在一些內部系統,甚至一些訪問量及其小的網站,完全可以不用快取,資料庫的性能其實并沒有那么不堪一擊,
無依賴輕量級快取
僅僅個別地方可能需要一些簡單的快取,那么可以直接在成員變數中使用Map(或ConcurrentHashMap)做簡單的快取,如果使用LRU快取淘汰,或者失效快取,可以簡單參考一些第三方工具類,如Guava的Cache,Hutool的Cache等,
Redis快取
Redis快取也是根據自己的需要來使用,從單機Redis到高可用的Redis集群,
單機Redis比較簡單,直接在一臺服務器上安裝一個Redis配置即可使用
高可用Redis有很多中方法,主從,哨兵,等,甚至可以買一些云服務的高可用Redis
由于Redis過于強大,使用方式也太多,這里不在一一說明,如有需要自行百度,
{
"author": "大火yzs",
"title": "【金三銀四】快取面試題-web層快取",
"tag": "Redis,快取,面試題",
"createTime": "2021-03-07 23:01"
}
本文由博客群發一文多發等運營工具平臺 OpenWrite 發布
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/267289.html
標籤:Java
下一篇:python時間模塊的使用
