首頁  >  文章  >  資料庫  >  20+道必知必會的Redis面試題總,快來收藏吧! !

20+道必知必會的Redis面試題總,快來收藏吧! !

青灯夜游
青灯夜游轉載
2021-04-14 10:33:402386瀏覽

這篇文章跟大家分享一下Redis面試題,方便大家查漏補缺,完善知識點。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

20+道必知必會的Redis面試題總,快來收藏吧! !

應用程式場景

  • #快取

  • 分享Session

  • 訊息佇列系統

  • 分散式鎖定

相關推薦:Redis視頻教學

單執行緒的Redis為什麼快

  • #純記憶體操作

  • ##單執行緒操作,避免了頻繁的上下文切換

  • 合理高效的資料結構

  • 採用了非阻塞I/O多路復用機制(有一個檔案描述子同時監聽多個檔案描述子是否有資料到來)

#Redis 的資料結構及使用場景

  • String字串:字串類型是Redis 最基礎的資料結構,首先鍵都是字串類型,而且其他幾種資料結構都是在字串類型基礎上建構的,我們常使用的set key value 指令就是字串。常用在快取、計數、共享Session、限速等。

  • Hash哈希:在Redis中,哈希類型是指鍵值本身又是一個鍵值對結構,哈希可以用來存放用戶信息,例如實現購物車。

  • List清單(雙向鍊錶):清單(list)類型是用來儲存多個有序的字串。可以做簡單的訊息佇列的功能。

  • Set集合:集合(set)類型也是用來保存多個的字串元素,但和清單類型不一樣的是,集合中不允許重複元素,並且集合中的元素是無序的,不能透過索引下標取得元素。利用 Set 的交集、並集、差集等操作,可以計算共同喜好,全部的喜好,自己獨有的喜好等功能。

  • Sorted Set有序集合(跳表實作):Sorted Set 多了一個權重參數 Score,集合中的元素能夠依 Score 進行排列。可以做排行榜應用,取 TOP N 操作。

Redis 的資料過期策略

#Redis 中資料過期策略採用

定期刪除惰性刪除策略

  • #定期刪除策略:Redis 啟用一個計時器定時監視所有的key,判斷key是否過期,過期的話就刪除。這種策略可以保證過期的key 最終都會被刪除,但是也存在嚴重的缺點:每次都遍歷內存中所有的數據,非常消耗CPU 資源,並且當key 已過期,但是定時器還處於未喚起狀態,這段時間內key 仍然可以用。

  • 惰性刪除策略:在取得 key 時,先判斷 key 是否過期,如果過期則刪除。這種方式有一個缺點:如果這個 key 一直未被使用,那麼它一直在記憶體中,其實它已經過期了,會浪費大量的空間。

  • 這兩種策略天然的互補,結合起來之後,定時刪除策略就發生了一些改變,不再是每次掃描全部的key 了,而是隨機抽取一部分key進行檢查,這樣就降低了對CPU 資源的損耗,惰性刪除策略互補了未檢查到的key,基本上滿足了所有要求。但有時候就是那麼的巧,既沒有被定時器抽取到,又沒有被使用,這些資料又如何從記憶體中消失?沒關係,還有記憶體淘汰機制,當記憶體不夠用時,記憶體淘汰機制就會上場。淘汰策略分為:當記憶體不足以容納新寫入資料時,新寫入操作會報錯。 (Redis 預設策略)當記憶體不足以容納新寫入資料時,在鍵空間中,移除最近最少使用的 Key。 (LRU建議使用)當記憶體不足以容納新寫入資料時,在鍵空間中,隨機移除某個 Key。當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,移除最近最少使用的 Key。這種情況一般是把 Redis 既當緩存,又做持久化儲存的時候才用。當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,隨機移除某個 Key。當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,有更早過期時間的 Key 優先移除。

Redis的set和setnx

Redis中setnx不支援設定過期時間,做分散式鎖定時要想避免某一客戶端中斷導致死鎖,需設定lock過期時間,在高並發時setnx與expire 無法實現原子操作,如果要用,得在程式碼上顯示的加鎖。使用SET取代SETNX ,相當於SETNX EXPIRE實現了原子性,不必擔心SETNX成功,EXPIRE失敗的問題。

Redis的LRU具體實作:

傳統的LRU是使用堆疊的形式,每次都會將最新使用的移入棧頂,但是用堆疊的形式會導致執行select *的時候大量非熱點資料佔領頭部數據,所以需要改進。 Redis每次按key取得一個值的時候,都會更新value中的lru欄位為目前秒等級的時間戳記。 Redis初始的實作演算法很簡單,隨機從dict中取出五個key,淘汰一個lru字段值最小的。在3.0的時候,又改進了一版演算法,首先第一次隨機選取的key都會放入一個pool中(pool的大小為16),pool中的key是按lru大小順序排列的。接下來每次隨機選取的keylru值必須小於pool中最小的lru才會繼續放入,直到將pool放滿。放滿之後,每次如果有新的key需要放入,需要將pool中lru最大的一個key取出。淘汰的時候,直接從pool中選取一個lru最小的值然後將其淘汰。

Redis如何發現熱點key

  • 憑藉經驗,進行預估:例如提前知道了某個活動的開啟,那麼就將此Key作為熱點Key。

  • 服務端收集:在操作redis之前,加入一行程式碼進行資料統計。

  • 抓包進行評估:Redis使用TCP協定與客戶端進行通信,通訊協定採用的是RESP,所以自己寫程式監聽埠也能進行攔截包進行解析。

  • 在proxy層,對每一個 redis 請求進行收集上報。

  • Redis自帶指令查詢:Redis4.0.4版本提供了redis-cli –hotkeys就能找出熱點Key。 (如果要用Redis自帶指令查詢時,要注意需要先把記憶體逐出策略設定為allkeys-lfu或volatile-lfu,否則會回傳錯誤。進入Redis中使用config set maxmemory-policy allkeys-lfu即可。 )

Redis的熱點key解決方案

  • 服務端快取:即將熱點資料快取至服務端的記憶體中.(利用Redis自帶的訊息通知機制來確保Redis和服務端熱點Key的資料一致性,對於熱點Key客戶端建立一個監聽,當熱點Key有更新操作的時候,服務端也隨之更新。)

  • 備份熱點Key:即將熱點Key 隨機數,隨機分配至Redis其他節點。這樣造訪熱點key的時候就不會全部命中到一台機器上了。

如何解決Redis 快取雪崩問題

  • 使用Redis 高可用架構:使用Redis 叢集來確保Redis 服務不會掛掉

  • 快取時間不一致,給快取的失效時間,加上一個隨機值,避免集體失效

  • 限流降級策略:有一定的備案,例如個性推薦服務不可用了,換成熱點資料推薦服務

如何解決Redis 快取穿透問題

  • 在介面做校驗

  • 存null值(快取擊穿加鎖,或設定不過期)

  • 布隆過濾器攔截:將所有可能的查詢key 先映射到布隆過濾器中,查詢時先判斷key是否存在布隆過濾器中,存在才繼續向下執行,如果不存在,則直接返回。布隆過濾器將值進行多次哈希bit存儲,布隆過濾器說某個元素在,可能會被誤判。布隆過濾器說某個元素不在,那一定不在。

Redis的持久化機制

Redis為了保證效率,資料快取在了記憶體中,但是會週期性地把更新的數據寫入磁碟或把修改操作寫入追加的記錄檔中,以確保資料的持久化。 Redis的持久化策略有兩種:

  • RDB:快照形式是直接把記憶體中的資料保存到一個dump的檔案中,定時保存,保存策略。當Redis需要做持久化時,Redis會fork一個子進程,子進程將資料寫到磁碟上一個臨時RDB檔案。當子進程完成寫入臨時檔案後,將原來的RDB替換掉。

  • AOF:把所有的對Redis的伺服器進行修改的命令都存到一個檔案裡,命令的集合。

使用AOF做持久化,每個寫入指令都透過write函數追加到appendonly.aof。 aof的預設策略是每秒鐘fsync一次,在這種配置下,就算發生故障停機,也最多遺失一秒鐘的資料。缺點是對於相同的資料集來說,AOF的檔案體積通常大於RDB檔案的體積。根據所使用的fsync策略,AOF的速度可能會慢於RDB。 Redis預設是快照RDB的持久化方式。對於主從同步來說,主從剛連接的時候,進行全量同步(RDB);全同步結束後,進行增量同步(AOF)。

Redis的事務

  • Redis 事務的本質是一組指令的集合。事務支援一次執行多個命令,一個事務中所有命令都會被序列化。在事務執行過程,會依照順序串列化執行佇列中的命令,其他客戶端提交的命令請求不會插入到交易執行命令序列中。總結:redis事務就是一次性、順序性、排他性的執行一個佇列中的一系列命令。

  • Redis事務沒有隔離等級的概念,批次操作在發送EXEC 指令前被放入佇列緩存,並不會實際執行,也就不存在事務內的查詢要看到事務裡的更新,事務外查詢不能看到。在

  • Redis中,單一指令是原子性執行的,但交易不保證原子性,且沒有回滾。事務中任意指令執行失敗,其餘的指令仍會被執行。

Redis事務相關指令

  • #watch key1 key2 ... : 監視一或多個key,如果在在事務執行之前,被監視的key被其他指令改動,則事務被打斷(類似樂觀鎖)

  • #multi : 標記一個事務區塊的開始(queued)

  • #exec : 執行所有事務區塊的命令(一旦執行exec後,先前加的監控鎖定都會被取消掉)

  • discard : 取消事務,放棄事務區塊中的所有指令

  • unwatch : 取消watch對所有key的監控

##Redis和memcached 的差異

  • 儲存方式上:memcache會把資料全部存在記憶體之中,斷電後會掛掉,資料不能超過記憶體大小。 redis有部分資料存在硬碟上,這樣能確保資料的持久性。

  • 資料支援類型上:memcache對資料型別的支援簡單,只支援簡單的key-value,,而redis支援五種資料型別。

  • 用底層模型不同:它們之間底層實作方式以及與客戶端之間通訊的應用協定不一樣。 redis直接自己建構了VM機制,因為一般的系統呼叫系統函數的話,會浪費一定的時間去移動和請求。

  • value的大小:redis可以達到1GB,而memcache只有1MB。

Redis的幾個群集模式

  • #主從複製

  • 哨兵模式

  • cluster模式

#Redis的哨兵模式##哨兵是分散式系統,在主從複製的基礎上你可以在一個架構中運行多個哨兵進程,這些進程使用流言協議來接收關於Master是否下線的信息,並使用投票協議來決定是否執行自動故障遷移,以及選擇哪個Slave作為新的Master。

每個哨兵會向其它哨兵、master、slave定時發送訊息,以確認對方是否活著,如果發現對方在指定時間(可配置)內未回應,則暫時認為對方已掛(所謂的”主觀認為宕機”)。

若「哨兵群「中的多數sentinel,都報告某一master沒響應,系統才認為該master"徹底死亡"(即:客觀上的真正down機),通過一定的vote演算法,從剩下的slave節點中,選一台提升為master,然後自動修改相關配置。

Redis的rehash

Redis的rehash 操作並不是一次性、集中式完成的,而是分多次、漸進式地完成的,redis會維護維持一個索引計數器變數rehashidx來表示rehash的進度。

這種漸進式的rehash 避免了集中式rehash帶來的龐大計算量和內存操作,但是需要注意的是redis在進行rehash的時候,正常的訪問請求可能需要做多要訪問兩次hashtable( ht[0], ht[1]),例如鍵值被rehash到新ht1,則需要先存取ht0,如果ht0中找不到,則去ht1中找。

Redis的hash表被擴展的條件

  • #哈希表中保存的key數量超過了哈希表的大小。

  • Redis伺服器目前沒有在執行BGSAVE指令(rdb)或BGREWRITEAOF指令,且雜湊表的負載因子大於等於1.

  • ##Redis伺服器目前正在執行BGSAVE指令(rdb)或BGREWRITEAOF指令,且雜湊表的負載因子大於等於5.(負載因子=雜湊表已保存節點數量/ 雜湊表大小,當雜湊表的負載因子小於0.1時,對哈希表執行收縮操作。)

Redis並發競爭key的解決方案

  • 分散式鎖定時間戳記

  • 利用訊息佇列

#Redis的管道pipeline

對於單執行緒阻塞式的Redis,Pipeline可以滿足批次的操作,把多個指令連續的傳送給Redis Server,然後一一解析回應結果。 Pipelining可以提高批次處理效能,提升的原因主要是TCP連線中減少了「交互往返」的時間。 pipeline 底層是透過把所有的操作封裝成流,redis有定義自己的出入輸出流。在 sync() 方法執行操作,每次請求放在佇列裡面,解析回應包。

Redis與Mysql雙寫一致性方案

先更新資料庫,再刪除快取。資料庫的讀取操作的速度遠快於寫入操作的,所以髒資料很難出現。可以對非同步延遲刪除策略,保證讀取請求完成以後,再進行刪除操作。

更多程式相關知識,請造訪:

程式設計影片! !

以上是20+道必知必會的Redis面試題總,快來收藏吧! !的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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