??大家好,我是陳哈哈,北漂五年,相信大家和我一樣,
都有一個大廠夢,作為一名資深Java選手,深知面試重要性,接下來我準備用100天時間,基于Java崗面試中的高頻面試題,以每日3題的形式,帶你過一遍熱門面試題及恰如其分的解答,
??一路走來,隨著問題加深,發現不會的也愈來愈多,但底氣著實足了不少,相信不少朋友和我一樣,榷訓月累才是最有效的學習方式!想起高三時一個同學的座右銘:只有沉下去,才能浮上來,共勉(juan),

坐標:成都 環球中心
作者:歪比巴卜
車票
- 面試題1:怎么解決快取穿透問題的
- 面試題2:說一下快取擊穿吧,你們是怎么解決的?
- 面試題3:那快取雪崩說說你們是怎么解決的
- 每日小結
??本欄目Java開發崗高頻面試題主要出自以下各技術堆疊:Java基礎知識、集合容器、并發編程、JVM、Spring全家桶、MyBatis等ORMapping框架、MySQL資料庫、Redis快取、RabbitMQ訊息佇列、Linux操作技巧等,
面試題1:怎么解決快取穿透問題的
快取穿透:指快取和資料庫中都沒有的資料,導致所有的請求都打到資料庫上,然后資料庫還查不到(如null),沒法寫快取,造成資料庫短時間執行緒數被打滿而導致其他服務阻塞,最終導致線上服務不可用,此時快取就好像被穿透了一樣,起不到任何作用,
當然,使用快取難免會有穿透的發生,
- 快取容量有限,不可能去快取所有資料,查詢到未被快取的資料就會發生穿透是正常情況,
- 互聯網業務的資料訪問模型一般是遵循
二八原則的,即 20% 的資料為熱點資料,80% 的資料是非熱點不被常訪問的資料,既然快取容量有限,且20%的資料為熱點資料,那我們可以利用有限的容量去快取那 20% 的資料來保護我們的系統,至于80%非熱點不常用的資料發生穿透就穿透了,資料庫吃得住,
??其實,只有大量穿透請求超過了我們后端系統的承受范圍,比如惡意的穿透攻擊,這樣的穿透才有可能把我們的系統給干崩,
??那我們怎樣來解決這種快取穿透問題呢?
- 介面引數校驗:
??防君子不防小人,在引數校驗層加上引數合法性校驗,如查詢訂單ID為20位隨機值,正則核對一下ID長度是否規范,不規范的直接過濾掉,
- 設定空值:
??當訪問快取和DB都沒有查詢到值時,該key我們當做是惡意引數來看,可以將該key的空值寫進快取,設定較短的過期時間,
??但是如果有大量的獲取并不存在資料的穿透請求的話如惡意攻擊,則會浪費快取空間,如果這種null值過量的話,還會淘汰掉本身快取存在的資料,這就會使我們的快取命中率下降,
??因此在使用設定空值方案時,我們要做好監控,預防快取空間被過多null值占領造成的快取空間浪費,如果這種資料量太大,就不再建議使用,那就使用另一種方案,即布隆過濾器,
- 布隆過濾器:
??布隆過濾器在查詢快取之前起到初步過濾作用,布隆過濾器存盤所有可能訪問的 key,將不存在的 key 直接過濾,存在的 key 再進一步查詢快取和資料庫,
??布隆過濾器的特點是判斷不存在的,則一定不存在;判斷存在的,大概率存在,但也有小概率不存在,并且這個概率是可控的,根據具體需求,我們可以讓這個概率小幅降低或變高,

??布隆過濾器由一個 bitSet 和 一組 Hash 函式(演算法)組成,是一種空間效率極高的概率型演算法和資料結構,通過二進制來進行資料存盤,在初始化時,bitSet 的每一位被初始化為0,
當資料加入布隆過濾器集合時,流程如下:

- 經過K個哈希函式計算該資料,回傳K個計算出的hash值
- 這些K個hash值映射到對應的K個二進制的陣列下標
- 將K個下標對應的二進制資料改為1,
布隆過濾器查詢一個key是否在集合中,流程如下:
- 經過K個哈希函式計算該資料,對應計算出的K個hash值
- 經過hash值找到對應的二進制的陣列下標
- 如果存在其中一處位置的二進制資料是0,那么該資料不存在,若是都是1,該資料存在集合中(但由于存在Hash碰撞,
判斷資料存在時可能存在誤判),
布隆過濾器的優缺點
優勢
- 因為存盤的是二進制資料,因此占用的空間很小;
- 它的插入和查詢速度是很是快的,時間復雜度是O(K),能夠聯想一下HashMap的程序;
- 保密性很好,由于自己不存盤任何原始資料,只有二進制資料
缺點
1、存在誤判
??添加資料是經過計算資料的hash值,hash是存在碰撞的,也就是說,存在兩個不一樣的資料計算獲得相同的hash值,

??例如圖中的你好和hello,假如最終算出hash值相同,那么他們會將同一個下標的二進制資料改成1,因此也無法確定key為你好和hello是否存在,
2、洗掉困難
??如上,你好和hello的hash值相同,對應的陣列下標也是同樣的,如果想洗掉你好,即將坐標值改為0,可能會影響到其他key,比如是否會連hello都一塊兒刪了之類的,

課間休息,來看看群里鐵子的組長小姐姐??
作者:W.M.H
面試題2:說一下快取擊穿吧,你們是怎么解決的?
快取擊穿:指快取中沒有但資料庫中有的資料(一般是熱點資料快取時間到期),這時由于并發用戶特別多,同時讀快取沒讀到資料,又同時去資料庫去查,引起資料庫壓力瞬間增大,線上系統卡住,
解決方案:
1、加互斥鎖(mutex key),在并發的多個請求中,只有第一個請求執行緒能拿到鎖并執行資料庫查詢操作,其他的執行緒拿不到鎖就阻塞等著,等到第一個執行緒將資料寫入快取后,直接走快取,
互斥鎖
??快取擊穿后,多個執行緒會同時去查詢資料庫的這條資料,那么我們可以在第一個查詢資料的請求上使用一個互斥鎖來鎖住它,
??其他的執行緒走到這一步拿不到鎖就等著,等第一個執行緒查詢到了資料,然后做快取,后面的執行緒進來發現已經有快取了,就直接走快取,
static Lock reenLock = new ReentrantLock();
public List<String> getData04() throws InterruptedException {
List<String> result = new ArrayList<String>();
// 從快取讀取資料
result = getDataFromCache();
if (result.isEmpty()) {
if (reenLock.tryLock()) {
try {
System.out.println("拿到鎖了,從DB獲取資料庫后寫入快取");
// 從資料庫查詢資料
result = getDataFromDB();
// 將查詢到的資料寫入快取
setDataToCache(result);
} finally {
reenLock.unlock();// 釋放鎖
}
} else {
result = getDataFromCache();// 先查一下快取
if (result.isEmpty()) {
System.out.println("我沒拿到鎖,快取也沒資料,先小憩一下");
Thread.sleep(100);// 小憩一會兒
return getData04();// 重試
}
}
}
return result;
}
2、熱點資料不過期,根據實際業務情況,在Redis中維護一個熱點資料表,批量設為永不過期(如top1000),并定時更新top1000資料,
??這種方式適用于比較極端的場景,例如流量特別特別大的場景,使用時需要考慮業務能接受資料不一致的時間,還有就是例外情況的處理,不要到時候快取重繪不上,一直是臟資料,那就涼了,

課間休息,來看看群里的lsp直呼西瓜真大的西瓜圖~,嗯,確實大!,
作者:好名字可以讓我的朋友更容易記住我
面試題3:那快取雪崩說說你們是怎么解決的
快取雪崩:大量的熱點 key 設定了相同的過期時間,導在快取在同一時刻全部失效,造成瞬時資料庫請求量大、壓力驟增,引起雪崩,甚至導致資料庫被打掛,快取雪崩其實有點像升級版的快取擊穿,快取擊穿是一個熱點 key,快取雪崩是一組熱點 key,
解決方案:
1、過期時間打散:既然是大量快取集中失效,那最容易想到就是讓他們不集中生效,可以給快取的過期時間時加上一個隨機值時間,使得每個 key 的過期時間分布開來,不會集中在同一時刻失效,
2、熱點資料不過期:快取永不過期,異步更新快取資料,隨不會出現雪崩效應,卻無法保證資料的一致性,
3、加互斥鎖:jvm鎖機制、分布式鎖機制都可以,該方式和快取擊穿一樣,按 key 維度加鎖,對于同一個 key,只允許一個執行緒去計算,其他執行緒原地阻塞等待第一個執行緒的計算結果,然后直接走快取即可,
每日小結
??今天我們復習了面試中常考的Redis相關的三個熱點問題,你做到心中有數了么?對了,如果你的朋友也在準備面試,請將這個系列扔給他,如果他認真對待,肯定會感謝你的!!好了,今天就到這里,學廢了的同學,記得在評論區留言:打卡,,給同學們以激勵,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/303871.html
標籤:java
