首頁  >  文章  >  資料庫  >  2023年Redis高頻面試題分享(附答案分析)

2023年Redis高頻面試題分享(附答案分析)

青灯夜游
青灯夜游轉載
2021-10-18 10:27:284800瀏覽

這篇文章為大家總結分享一些Redis高頻面試題,有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

2023年Redis高頻面試題分享(附答案分析)

面試官心理分析

從面試官的角度分析,出這題的目的是為了檢視你對快取的認知水平,以及結合快取處理業務、改善架構的能力。這題很明顯是讓你自由發揮,給了你引領面試官往自己最熟悉的知識點引導的機會,所以要盡可能的把握這次機會,給面試官一個好的印象。這題聊得好,就是能深入交流個把小時了,如果是一面基本上能輕輕鬆鬆拿下。 【相關推薦:Redis影片教學

但是千萬不要上來就把話題聊死了,聊太淺了, 那基本上就是回去等通知了……


例如以下這種回答方式:

2023年Redis高頻面試題分享(附答案分析)

#很多人會說這麼回答也沒錯!沒錯是沒錯,但總有一種給你機會不中用的感覺。

此時此刻面試官內心想發大致是這樣的:

  • #比較基礎,應該沒有很深入的了解Redis
  • #想問題停留在表面呀,估計平時就知道幹活,沒想過問題
  • #給你自由發揮的機會,你不把握呀,看樣子還是得我自己來,先問你幾個分散式、持久化的問題看看水平怎麼樣,不行就這樣了吧,後面還有好多人,等會要下班了。

如果不想硬抗下面試官的降龍十八掌,就應該主動挑起面試官的興趣,並且把自己的格局(水平廣度和深度)率先提升起來,將自己會的東西盡可能的多講一些出來。

例如以下這種回答方式:

2023年Redis高頻面試題分享(附答案分析)

#Redis面試題總結

2023年Redis高頻面試題分享(附答案分析)

這個我的理解大致上是這樣的面試官! !

高效能:高效能一個很大的標準,就是反應時間快。 Redis基於記憶體存儲,CPU存取速度快,此外Redis對於資料結構的極致優化、內部線程模型和網路I/O模型的設計,決定了Redis是一個高效能儲存資料庫。唯一的缺點就是記憶體比較昂貴,通常資源比較有限,因此對於非常大的資料快取架構應該合理設計,我們通常不會在Redis中存放過大的數據,因為這樣會導致Redis效能下降。

高並發:高並發通常指標有回應時間(Response Time),吞吐量(Throughput),每秒查詢率QPS(Query Per Second)和並髮用戶數等,Redis雖然它是一個單一進程單線程模型,但是Redis確實高並發業務場景下的一把利器,目前Redis的QPS已經能達到10萬甚至是100萬級別了,這是絕對的高並發。

高可用:Redis高可用主要體現在主從複製、sentinel(哨兵模式)和Cluster(叢集模式)三者

2023年Redis高頻面試題分享(附答案分析)

這我的理解大致是這樣的面試官! !

Redis的單線程指的是執行命令操作使用單線程,Redis6.x發布之後使用多線程處理網路資料的讀寫和協議解析,Redis單線程這麼快的原因主要有這些點:

  • 採用I/O多路復用非阻塞模型處理客戶端socket連接,能夠極大的優化Redis服務端響應速度和效率,多路I/O 復用技術可以讓單一線程高效的處理多個連線請求,盡量減少網路IO 的時間消耗。
  • 基於記憶體存儲,減少磁碟IO,讀取速度快
  • Redis對內部資料結構做了極致的最佳化,使Redis的資料結構非常有效率。並且在不同的資料量和儲存內容採取不同的編碼方式,這涉及了 Redis 底層的編碼轉換。例如list、hash、zset 三個鍵使用到了ziplist 壓縮列表編碼,ziplist 是一種結構緊湊的資料結構,當某一鍵值所包含的元素較少時,會優先儲存在ziplist 中,當元素個數超過某一值後,才將ziplist 轉換為標準儲存結構,當然這個值是在redis.conf中可自訂配置。此外SDS的記憶體預先分配、Hash結果Rehash中的漸進式hash、ZSet順序基於SkipList存儲,都優化了資料結構,使其更快。
  • Redis在執行命令操作使用單線程,無需考慮並發鎖的設計,以及多線程帶來的CPU上下文切換消耗,因此執行命令更快

2023年Redis高頻面試題分享(附答案分析)

這個我的理解大致上是這樣的面試官! !

Redis有5種基本資料型別它們分別是String、List、Hash、Set、ZSet;此外還有三種特殊資料型別Bitmaps、Geospatial、HyperLogLog

######
資料類型 簡單描述 使用場景
String string(字串)是Redis最簡單也是使用最廣泛的資料結構,它的內部是一個字元陣列。 String(字串)是動態字串,允許修改;它在結構上的實作類似於Java中的ArrayList(預設建構一個大小為10的初始陣列),這是冗餘分配記憶體的思想,也稱為預分配;這種想法可以減少擴容帶來的性能消耗。當string(字串)的大小達到擴容閾值時,將會對string(字串)進行擴容,string(字串)的擴容主要有三種情況:1.長度小於1MB,擴容後為原先的兩倍; length = length * 2 2.長度大於1MB,擴容後增加1MB; length = length 1MB 3. 字串的長度最大值為512MB 快取、計數器、分散式鎖定等。
List Redis的清單相當於Java語言中的LinkedList,它是雙向鍊錶資料結構(但這個結構設計比較巧妙,後面會介紹),支援前後順序遍歷。鍊錶結構插入與刪除操作快,時間複雜度O(1),查詢慢,時間複雜度O(n)。 Redis的list(列表)不是一個簡單。 LinkedList,而是quicklist ——“快速列表”,quicklist是多個ziplist(壓縮列表)組成的雙向列表; 鍊錶、非同步隊列、微博關注人時間軸列表…
Hash Redis的hash(字典)相當於Java語言中的HashMap,它是根據雜湊值分佈的無序字典,內部的元素是透過鍵值對的方式儲存。 hash(字典)的實作與Java中的HashMap(JDK1.7)的結構也是一致的,它的資料結構也是由陣列鍊錶組成的二維結構,節點元素散列在陣列上,如果發生hash碰撞則使用鍊錶串聯在數組節點上。 Redis中的hash(字典)儲存的value只能是字串值,此外擴充與Java中的HashMap也不同。 Java中的HashMap在擴容的時候是一次性完成的,而Redis考慮到其核心存取是單執行緒的效能問題,為了追求高效能,因而採取了漸進式rehash策略。漸進式rehash指的是並非一次性完成,它是多次完成的,因此需要保留舊的hash結構,所以Redis中的hash(字典)會存在新舊兩個hash結構,在rehash結束後也就是舊hash的值全部搬遷到新hash之後,新的hash在功能上才會完全取代先前的hash。 使用者資訊、Hash 表…
Set #Redis的set(集合)相當於Java語言裡的HashSet,它內部的鍵值對是無序的、唯一的。它的內部實作了一個所有value為null的特殊字典。集合中的最後一個元素被移除之後,資料結構被自動刪除,記憶體被回收。 去重功能、讚、踩、共同好友…
ZSet zset(有序集合)是Redis中最常問的資料結構。它類似於Java語言中的SortedSet和HashMap的結合體,它一方面透過set來保證內部value值的唯一性,另一方面透過value的score(權重)來進行排序。這個排序的功能是透過Skip List(跳躍列表)來實現的。 zset(有序集合)的最後一個元素value被移除後,資料結構被自動刪除,記憶體被回收。 粉絲清單、學生成績排序、訪問量排行榜、點擊量排行榜…
#Bitmaps Bitmaps 稱為點陣圖,嚴格來說它不是一種資料型態。 Bitmaps底層就是字串(key-value)byte陣列。我們可以使用普通的get/set直接取得和設值位圖的內容,也可以透過Redis提供的點陣圖操作getbit/setbit等將byte陣列看成「位元組」來處理。 Bitmaps 的「位數組」每個單元格只能儲存0和1,數組的下標在Bitmaps中稱為偏移量。 Bitmaps設定時key不存在會自動產生一個新的字串,如果設定的偏移量超出了現有內容的範圍,就會自動將位數組進行零擴充 員工打卡…
Geospatial Geospatial是Redis在3.2版本以後增加的地理位置GEO模組 微信附近的人,線上點餐「附近的餐廳」… …
HyperLogLog HyperLogLog是用來做基數統計的演算法,它提供不精確的去重計數方案(這個不精確並不是非常不精確),標準誤差是0.81%,對於UV這種統計來說這樣的誤差範圍是被允許的。 HyperLogLog的優點在於,輸入元素的數量或體積非常大時,基數計算的儲存空間是固定的。在Redis中,每個HyperLogLog鍵只需要花費12KB內存,就可以計算接近2^64個不同的基數。但是HyperLogLog只能統計基數的大小(也就是資料集的大小,集合的個數),他不能儲存元素的本身,不能向set集合那樣儲存元素本身,也就是說無法傳回元素。 基數統計例如UV等
#

2023年Redis高頻面試題分享(附答案分析)

這個我的理解大致上是這樣的面試官! !

Redis的資料結構都可以透過EXPIRE key seconds 的方式設定key的過期時間(TTL)。我們也習慣的認為Redis的key過期時間到了,就會自動刪除,顯然這種想法並不正確。 Redis的設計考慮到性能/記憶體等綜合因素,設計了一套過期策略。

  • 主動刪除(惰性刪除)
  • 被動刪除(定期策略)

#主動刪除(惰性刪除)指的是當key被存取的時候,先校驗key是否過期,如果過期了則主動刪除。

被動刪除(定期策略)指的是Redis伺服器定時隨機的測試key的過期時間,如果過期了則被動刪除。被動刪除的存在必不可少,因為存在一些過期且永久不在存取的key,如果都依賴主動刪除,那麼它們將會永久佔用記憶體。

Redis為了確保提供高效能服務,被動刪除過期的key,採用了貪心策略/機率演算法,預設每隔10秒掃描一次,具體策略如下:

  • 1、從過期字典(設定了過期時間的key的集合)中隨機選擇20個key,檢查其是否過期

  • 2、刪除其中已經過期的key

  • 3、如果刪除的過期key數量大於25%,則重複步驟1

此外開發在設計Redis快取架構時,一定要注意要盡可能的避免(禁止)將大量的key設定為同一過期時間,因為結合被動刪除可知,Redis被動刪除過期key時,會導致服務短暫的不可用;如果存在大量key同時過期,這會導致被動刪除key的三個步驟循環多次,從而導致Redis服務出現卡頓情況,這種情況在大型流量項目中是無法接收的。

因此為了避免這種情況出現,一定要將一些允許過期時間不需要非常精確的key,設定較為隨機的過期時間,這樣就可以將卡頓時間縮小。

2023年Redis高頻面試題分享(附答案分析)

這個我的理解大致上是這樣的面試官! !

在分散式場景中我們常見的分散式鎖定解決方案有(如果自己都會可以把其他兩種也在這帶出來,如果不會那就別把自己坑了呀! ):

  • 基於資料庫鎖定機制實作的分散式鎖定

  • #基於Zookeeper實作的分散式鎖定

  • 基於Redis實作的分散式鎖定

而關於Redis實現分散式鎖定的方案是這樣的。

如果Redis是在單機環境中, 我們可以透過,Redis提供的原子指令來實作分散式鎖定

set key value [EX seconds] [PX milliseconds ] [NX|XX]

為了防止A加的鎖,被B刪除了,可以加鎖時傳入客戶端加鎖標記,只有當客戶端傳入的標記和鎖標記相同時才允許解鎖,不過Redis並未提供這樣的功能,我們只能透過Lua腳本來處理,因為Lua腳本可以保證多個指令的原子性執行。最後我們還要考慮鎖的超時問題,如果客戶端一直不釋放鎖肯定也是不行的,因此鎖只能保證在指定的超時時間範圍內不被其他客戶端解鎖,超時之後就自動釋放了,這種情況很難我們可以這樣優化:

  • 盡可能不要在Redis分散式鎖定中執行較長的任務,盡可能的縮小鎖定區間內執行程式碼,就像單一JVM鎖定中的synchronized優化一樣,我們可以考慮優化鎖的區間

  • #多做壓力測試和線上真實場景的模擬測試,估算一個合適的鎖定逾時時間

  • #做好Redis分散式鎖定逾時任務未執行完的問題發生後,資料復原手段的準備

如果是在分散式環境中, 會增加一個新的問題,例如sentinel 一主多從環境中,可能存在客戶端在主節點上申請了鎖,但是同步未完成,主節點宕機了,此時新選舉的主節點上鎖是失效的。

對於這種情況的處理應該是這麼考慮的,首先Redis主從同步直接無論如何都無法解決資料會有遺失的情況。所以我們考慮把像一個Redis申請鎖,變成像多個單機Redis申請鎖,只有大部分申請成功就行。這個想法就是RedLock(紅鎖)。

RedLock透過使用多個Redis實例,各個實例之間沒有主從關係,相互獨立;加鎖的時候,客戶端向所有的節點發送加鎖指令,如果過半的節點set成功,就加鎖成功。釋放鎖定時,需要向所有的節點發送del指令來釋放鎖定。

紅鎖雖然解決了主從同步的問題,但是帶來新的複雜問題:

  • 第一個問題是時脈漂移
  • 第二個問題是客戶端像不同的Redis服務端申請鎖定成功的時間是不同的
##因此在RedLock中需要計算申請的鎖的最小有效時長。假設客戶端申請鎖定成功,第一個key設定成功的時間為TF,最後一個key設定成功的時間為TL,鎖的逾時時間為TTL,不同行程之間的時脈差異為CLOCK_DIFF,則鎖的最小有效時長是:

TIME = TTL - (TF- TL) - CLOCK_DIFF

採用Redis來實現分散式鎖,離不開伺服器宕機等不可用問題,這裡RedLock紅鎖也是一樣,即使是多台伺服器申請鎖,我們也要考慮伺服器宕機後的處理,官方建議採用AOF持久化處理。

但是AOF持久化只對正常SHUTDOWN這種指令能做到重啟恢復,但是如果是斷電的情況,可能導致最後一次持久化到斷電期間的鎖定資料遺失,當伺服器重新啟動後,可能會出現分散式鎖定語意錯誤的情況。所以為了規避這種情況,官方建議Redis服務重啟後,一個最大客戶端TTL時間內該Redis服務不可用(不提供申請鎖的服務),這確實可以解決問題,但是顯而易見這肯定影響Redis伺服器的效能,並且在多數節點都出現這種情況的時候,系統將出現全域不可用的狀態。

2023年Redis高頻面試題分享(附答案分析)

這個我的理解大致上是這樣的面試官! !

Redis的非常快,很大一部分原因是因為Redis的資料儲存在記憶體中,既然在記憶體中,那麼當伺服器宕機或斷電的時候,資料就會全部遺失了,所以Redis提供了兩種機制來確保Redis資料不會因為故障而全部遺失,這種機制稱為Redis的持久化機制。

Redis的持久化機制有兩種:

    RDB(Redis Data Base) 記憶體快照
  • AOF(Append Only File) 增量日誌

RDB(Redis DataBase) 指的是指定的時間間隔內將記憶體中的資料集快照寫入磁碟,RDB是記憶體快照(記憶體資料的二進位序列化形式)的方式持久化,每次都是從Redis產生一個快照進行資料的全量備份。

優點:

    儲存緊湊,節省記憶體空間
  • 恢復速度非常快
    適合全量備份、全量複製的場景,經常用於災難復原(對資料的完整性和一致性要求相對較低的場合)

缺點:

    #容易遺失數據,容易遺失兩次快照之間Redis伺服器中變化的數據。
  • RDB透過fork子程序對記憶體快照進行全量備份,是一個重量級操作,頻繁執行成本高。
    fork子進程,雖然共享內存,但是如果備份時內存被修改,最大可能會膨脹到2倍大小。
RDB觸發的規則分為兩大類,分別是手動觸發和自動觸發:

#自動觸發:

  • 設定觸發規則

  • shutdown觸發

  • flushall觸發
手動觸發:

  • save

  • bgsave

#AOF(Append Only File) 是把所有對記憶體進行修改的指令(寫入操作)以獨立日誌檔案的方式進行記錄,重啟時透過執行AOF檔案中的Redis指令來復原資料。 AOF能夠解決資料持久化即時性問題,是現在Redis持久化機制中主流的持久化方案(後續會談到4.0以後的混合持久化)。

優點:

    資料的備份更完整,遺失資料的機率更低,適合資料完整性要求高的場景
  • #日誌檔案可讀,AOF可操作性更強,可透過操作日誌檔案進行修正

#缺點:

    AOF日誌記錄在長期運作中逐漸龐大,恢復起來非常耗時,需要定期對AOF日誌進行瘦身處理(後續詳述)
  • 恢復備份速度比較慢
##同步寫操作頻繁會帶來效能壓力
  • AOF日誌是以檔案的形式存在的,當程式對AOF日誌檔案進行寫入操作時,實際上將內容寫到了核心為檔案描述符分配的在一個記憶體緩衝區中,隨後核心會異步的將緩衝區中的資料刷新到磁碟中。如果緩衝區中的資料來不及刷回磁碟時,伺服器宕機了,這些資料就會遺失。

因此Redis透過呼叫Linux作業系統的glibc提供的fsync(int fid)來強制將指定檔案的內容從核心緩衝區刷回磁碟,以確保緩衝區中的資料不會遺失。不過這是一個IO操作,比起Redis的效能來說它是非常慢的,所以不能頻繁的執行。

Redis設定檔中有三種刷新緩衝區的設定:

appendfsync always

#

每次Redis寫入操作,都寫入AOF日誌,這種配置理論上Linux作業系統扛不住,因為Redis的並發遠遠超過了Linux作業系統提供的最大刷新頻率,就算Redis寫操作比較少的情況,這種配置也是非常耗性能的,因為涉及IO操作,所以這個配置基本上不會用

appendfsync everysec

##每秒刷新一次緩衝區中的資料到AOF文件,這個Redis配置檔案中預設的策略,相容了效能和資料完整性的折中方案,這種配置,理論上遺失的資料在一秒鐘左右

#appendfsync no

Redis進程不會主動的去刷新緩衝區中的資料到AOF檔中,而是直接交給作業系統去判斷,這種操作也是不建議的,遺失資料的可能性非常大。

前面提到AOF的缺點時,說過AOF屬於日誌追加的形式來存儲Redis的寫指令,這會導致大量冗餘的指令存儲,從而使得AOF日誌檔案非常龐大,這種情況不僅佔內存,也會導致恢復的時候非常緩慢,因此Redis提供重寫機制來解決這個問題。 Redis的AOF持久化機制執行重寫後,保存的只是恢復資料的最小指令集,我們如果想手動觸發可以使用如下指令

bgrewriteaof

Redis4.0後的重寫使用的是RDB快照和AOF指令拼接的方式,在AOF檔案的頭部是RDB快照的二進位形式的數據,尾部是快照產生後發生的寫入操作的指​​令。

由於重寫AOF檔時,會對Redis的效能帶來一定的影響,因此也不能隨便的進行自動重寫,Redis提供兩個配置用於自動進行AOF重寫的指標,只有這兩個指標同時滿足的時候才會發生重寫:

auto-aof-rewrite-percentage 100:指的是當檔案的記憶體達到原先記憶體的兩倍

#auto-aof-rewrite-min-size 64mb:指的是檔案重寫的最小記憶體大小

此外Redis4.0後大部分的使用情境都不會單獨使用RDB或AOF來做持久化機制,而是兼顧二者的優勢混合使用。

最後來總結這兩者,到底用哪個比較好呢?

    推薦是兩者皆開啟
  • 如果對資料不敏感,可以選單獨用RDB
    不建議單獨用AOF,因為可能會出現Bug
  • 如果只是做純記憶體緩存,可以都不要用

2023年Redis高頻面試題分享(附答案分析)

這個我的理解大致上是這樣的面試官! !

Redis是基於記憶體儲存的key-value資料庫,我們知道記憶體雖然快但空間小,當實體記憶體達到上限時,系統就會跑的很慢,所以我們會設定Redis的最大內存,當Redis內存達到設定閾值的時候會觸發內存回收,Redis提供了很多內存淘汰策略:

  • noeviction: 當達到內存限制並且客戶端嘗試執行可能導致使用更多記憶體的命令時返回錯誤,簡單來說讀取操作仍然允許,但是不准寫入新的數據,del(刪除)請求可以
  • allkeys-lru: 從全體key中,透過lru(Least Recently Used - 最近最少使用)演算法進行淘汰
  • allkeys-random: 從全體key中,隨機進行淘汰
  • volatile-lru: 從設定了過期時間的全部key中,透過lru(Least Recently Used - 最近最少使用)演算法進行淘汰,這樣可以保證未設定過期時間需要被持久化的數據,不會被選中淘汰
  • #volatile-random: 從設定了過期時間的全部key中,隨機進行淘汰
  • volatile-ttl: 從設定了過期時間的全部key中,透過比較key的剩餘過期時間TTL的值,TTL越小越先被淘汰
  • volatile-lfu: 對有過期時間的key採用LFU淘汰演算法
  • allkeys-lfu: 對全部key採用LFU淘汰演算法
在這些策略中有兩個比較重要的演算法一個是LRU,也就是淘汰最近最少使用的key。不過Redis使用了近似LRU演算法,並不是完完全全準確的淘汰掉最近最不常使用的key,但是整體的準確度也可以得到保證。

近似LRU演算法非常簡單,在Redis的key物件中,增加24bit用於儲存最近一次存取的系統時間戳,當客戶端對Redis服務端發送key的寫入相關請求時,發現內存達到maxmemory,此時觸發惰性刪除;Redis服務通過隨機採樣,選擇5個滿足條件的key(注意這個隨機採樣

allkeys-lru是從所有的key中隨機採樣,volatile- lru是從所有設定了過期時間的key中隨機取樣),透過key物件中記錄的最近存取時間戳進行比較,淘汰掉這5個key中最舊的key;如果記憶體仍然不夠,就繼續重複這個步驟。

在Redis 3.0 maxmemory_samples設定為10的時候,Redis的近似LRU演算法已經非常的接近真實LRU演算法了,但是顯然maxmemory_samples設定為10比maxmemory_samples 設定為5要更加消耗CPU計算時間,因為每次採樣的樣本資料增大,計算時間也會增加。

Redis3.0的LRU比Redis2.8的LRU演算法更準確,是因為Redis3.0增加了一個與maxmemory_samples相同大小的淘汰池,每次淘汰key的時候,先與淘汰池中等待被淘汰的key進行比較,最後淘汰掉最老舊的key,其實就是被選中淘汰的key放到一起再比較一下,淘汰其中最舊的。

LRU有一個明顯的缺點,它無法正確的表示一個Key的熱度,如果一個key從未被訪問過,僅僅發生內存淘汰的前一會兒被用戶訪問了一下,在LRU算法中這會被認為是一個熱key。 LFU(Least Frequently Used)是Redis 4.0 引入的淘汰演算法,它透過key的存取頻率比較來淘汰key,重點突出的是Frequently Used。

LRU與LFU的差異:

  • LRU -> Recently Used,根據最近一次造訪的時間比較
  • LFU -> ; Frequently Used,根據key的存取頻率比較

在LFU模式下,Redis物件頭的24bit lru欄位被分成兩段來存儲,高16bit儲存ldt(Last Decrement Time),低8bit儲存logc(Logistic Counter)。高16bit用來記錄最近一次計數器降低的時間,由於只有8bit,儲存的是Unix分鐘時間戳取模2^16,16bit能表示的最大值為65535(65535/24/60≈ 45.5),大概45.5天會折返(折返指的是取模後的值重新從0開始)。

低8位元用來記錄存取頻次,8bit能表示的最大值為255,logc肯定無法記錄真實的Rediskey的存取次數,其實從名字可以看出儲存的是存取次數的對數值,每個新加入的key的logc初始值為5(LFU_INITI_VAL),這樣可以保證新加入的值不會被先選取淘汰;logc每次key被存取時都會更新;此外,logc會隨著時間衰減。

Logistic Counter不僅會成長,也會衰弱,成長和衰弱的規則也可以透過redis.conf進行設定。

  • lfu-log-factor 用來調整Logistic Counter的成長速度,lfu-log-factor值越大,Logistic Counter成長越慢。
  • lfu-decay-time 用來調整Logistic Counter的衰減速度,它是一個以分鐘為單位的數值,預設值為1,;lfu-decay-time值越大,衰減越慢。

2023年Redis高頻面試題分享(附答案分析)

這個我的理解大致上是這樣的面試官! !

快取擊穿:

就是說某個存取非常頻繁的熱點key ,處於集中式高並發存取的情況,當這個key 在失效的瞬間,大量的請求就擊穿了緩存,直接請求資料庫,直接穿過了Redis。

解決方式:

  • 若快取的資料比較固定,則可嘗試將該熱點資料設定為永不過期。
  • 若快取的資料更新不頻繁,且快取刷新的整個流程耗時較少的情況下,則可以採用基於Redis、zookeeper 等分散式中間件的分散式互斥鎖,或者本地互斥鎖以確保僅少量的請求能請求資料庫並重新建構緩存,其餘執行緒則在鎖定釋放後能存取新快取。
  • 若快取的資料更新頻繁或是在快取刷新的流程耗時較長的情況下,可以利用定時執行緒在快取過期前主動地重新建構快取或延後快取的過期時間,以確保所有的請求能一直存取到對應的快取。

快取穿透:

指的是快取和資料庫中都不存在的資料被請求,這種情況通常是被駭客攻擊力,如果不做好防禦很容易導致資料庫被請求打死。例如駭客使用負數id查詢你的某個表,我們的id通常不會設定為負數。

解決方式:

  • 資料庫未查詢到,則在快取中設定一個空值,這種方法無法解決採用不同負數id請求的情況。
  • 使用布隆過濾器,將資料庫中所有的資料對應到布隆過濾器中,請求打過來之前先用布隆過濾器判斷是否存在,不存在直接返回就行。

快取雪崩:

快取雪崩發生在大量快取同時失效的情況,會導致資料庫瞬間崩潰(高並發場景),而且這種情況下如果快取不恢復,資料庫起來也沒用,還是會繼續被打崩。

解決方式:

  • 快取架構設計:設計高可用Redis,主從sentinel,Redis cluster叢集
  • 專案服務端:使用本機快取和服務降級處理,盡量減少請求打到MySQL
  • #維運手段:定期監控Redis集群,做持久化的備份機制,一旦雪崩還能及時恢復快取資料

12023年Redis高頻面試題分享(附答案分析)

差不多回答到這裡,面試官的臉色露出了久違的微笑,我們接下來只有接住這一招,這次面試就有了。

當然關於這個知識點不是幾句話能說清楚的,所以建議大家看看這篇文章,就可以輕鬆hold住了

Redis分散式——主從複製、Sentinel、群集徹底吃透

本文轉載自:https://juejin.cn/post/7019088999792934926

作者:李子捌

更多程式相關知識,請造訪:程式設計入門! !

以上是2023年Redis高頻面試題分享(附答案分析)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除