天天看點

Java面試題-redis7

作者:Java農夫

又是一年招聘季,整理一些面試題,為自己也為大家整理點資料,希望大家成功上岸。這些整理的是針對面試。因平台單日有釋出數量限制,超出限制的隻能粉絲檢視,需要的請關注後自行擷取,謝謝。

1、什麼是緩存擊穿?該如何解決

緩存擊穿是指一個Key非常熱點,在不停的扛着大并發,大并發集中對這一個點進行通路,當這個Key在失效的瞬間,持續的大并發就穿破緩存,直接請求資料庫,就像在一個完好無損的桶上鑿開了一個洞。

緩存擊穿的話,設定熱點資料永遠不過期。或者加上互斥鎖就能搞定了。

使用互斥鎖

業界比較常用的做法,是使用mutex。簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作傳回值的操作(比如Redis的SETNX)去set一個mutex key,當操作傳回成功時,再進行load db的操作并回設緩存;否則,就重試整個get緩存的方法。

僞代碼如下圖:

Java面試題-redis7

永遠不過期

這裡的“永遠不過期”包含兩層意思:

(1) 從redis上看,确實沒有設定過期時間,這就保證了,不會出現熱點key過期問題,也就是“實體”不過期。

(2) 從功能上看,如果不過期,那不就成靜态的了嗎?是以我們把過期時間存在key對應的value裡,如果發現要過期了,通過一個背景的異步線程進行緩存的建構,也就是“邏輯”過期

從實戰看,這種方法對于性能非常友好,唯一不足的就是建構緩存時候,其餘線程(非建構緩存的線程)可能通路的是老資料,但是對于一般的網際網路功能來說這個還是可以忍受。

2、什麼是緩存穿透?該如何解決

緩存穿透

是指查詢一個根本不存在的資料,緩存層和存儲層都不會命中,于是這個請求就可以随意通路資料庫,這個就是緩存穿透,緩存穿透将導緻不存在的資料每次請求都要到存儲層去查詢,失去了緩存保護後端存儲的意義。

造成緩存穿透的基本原因有兩個。

  • 第一,自身業務代碼或者資料出現問題,比如,我們資料庫的 id 都是1開始自增上去的,如發起為id值為 -1 的資料或 id 為特别大不存在的資料。如果不對參數做校驗,資料庫id都是大于0的,我一直用小于0的參數去請求你,每次都能繞開Redis直接打到資料庫,資料庫也查不到,每次都這樣,并發高點就容易崩掉了。
  • 第二,一些惡意攻擊、爬蟲等造成大量空命中。。
Java面試題-redis7

如何解決

  • 緩存空對象

當存儲層不命中,到資料庫查發現也沒有命中,那麼仍然将空對象保留到緩存層中,之後再通路這個資料将會從緩存中擷取,這樣就保護了後端資料源。不過空值做了緩存,意味着緩存層中存了更多的鍵,需要更多的記憶體空間(如果是攻擊,問題更嚴重),比較有效的方法是針對這類資料設定一個較短的過期時間,讓其自動剔除。

  • 布隆過濾器攔截

在通路緩存層和存儲層之前,将存在的key用布隆過濾器提前儲存起來,做第一層攔截。例如:一個推薦系統有4億個使用者id,每個小時算法工程師會根據每個使用者之前曆史行為計算出推薦資料放到存儲層中,但是最新的使用者由于沒有曆史行為,就會發生緩存穿透的行為,為此可以将所有推薦資料的使用者做成布隆過濾器。如果布隆過濾器認為該使用者id不存在,那麼就不會通路存儲層,在一定程度保護了存儲層。

Java面試題-redis7

這種方法适用于資料命中不高、資料相對固定、實時性低(通常是資料集較大)的應用場景,代碼維護較為複雜,但是緩存空間占用少。

繼續閱讀