Redis 精選 30 道面試題
大家好,我是賀同學,分享好朋友 moon 老哥的 Redis 面試總結。
redis 作爲我們最常用的內存數據庫,很多地方你都能夠發現它的身影,比如說登錄信息的存儲,分佈式鎖的使用,其經常被我們當做緩存去使用。
可是,用了這麼久的 reids,你懂它嗎?
-
- 什麼是 redis?它能做什麼?
-
- redis 有哪八種數據類型?有哪些應用場景?
-
- redis 爲什麼這麼快?
-
- 聽說 redis 6.0 之後又使用了多線程,不會有線程安全的問題嗎?
-
- redis 的持久化機制有哪些?優缺點說說
-
- Redis 的過期鍵的刪除策略有哪些?
-
- Redis 的內存滿了怎麼辦?
-
- Redis 的熱 key 問題怎麼解決?
-
- 緩存擊穿、緩存穿透、緩存雪崩是什麼?怎麼解決呢?
-
- Redis 有哪些部署方式?
-
- 哨兵有哪些作用?
-
- 哨兵選舉過程是怎麼樣的?
-
- cluster 集羣模式是怎麼存放數據的?
-
- cluster 的故障恢復是怎麼做的?
-
- 主從同步原理是怎樣的?
-
- 無硬盤複製是什麼?
1. 什麼是 redis?它能做什麼?
redis: redis 即 Remote Dictionary Server,用中文翻譯過來可以理解爲遠程數據服務或遠程字典服務。其是使用 C 語言的編寫的 key-value 存儲系統
應用場景: 緩存,數據庫,消息隊列,分佈式鎖,點贊列表,排行榜等等
2.redis 有哪八種數據類型?有哪些應用場景?
redis 總共有八種數據結構,五種基本數據類型和三種特殊數據類型。
-
1.string: 字符串類型,常被用來存儲計數器,粉絲數等,簡單的分佈式鎖也會用到該類型
-
2.hashmap:key - value 形式的,value 是一個 map
-
3.list: 基本的數據類型,列表。在 Redis 中可以把 list 用作棧、隊列、阻塞隊列。
-
4.set: 集合,不能有重複元素,可以做點贊,收藏等
-
5.zset: 有序集合,不能有重複元素,有序集合中的每個元素都需要指定一個分數,根據分數對元素進行升序排序。可以做排行榜
三種特殊數據類型: -
1.geospatial: Redis 在 3.2 推出 Geo 類型,該功能可以推算出地理位置信息,兩地之間的距離。
-
2.hyperloglog: 基數:數學上集合的元素個數,是不能重複的。這個數據結構常用於統計網站的 UV。
-
3.bitmap: bitmap 就是通過最小的單位 bit 來進行 0 或者 1 的設置,表示某個元素對應的值或者狀態。一個 bit 的值,或者是 0,或者是 1;也就是說一個 bit 能存儲的最多信息是 2。bitmap 常用於統計用戶信息比如活躍粉絲和不活躍粉絲、登錄和未登錄、是否打卡等。
3.redis 爲什麼這麼快?
官方數據 redis 可以做到每秒近 10w 的併發,這麼快的原因主要總結爲以下幾點:
-
1: 完全基於內存操作
-
2: 使用單線程模型來處理客戶端的請求,避免了上下文的切換
-
3:IO 多路複用機制
-
4: 自身使用 C 語言編寫,有很多優化機制,比如動態字符串 sds
4. 聽說 redis 6.0 之後又使用了多線程,不會有線程安全的問題嗎?
不會
其實 redis 還是使用單線程模型來處理客戶端的請求,只是使用多線程來處理數據的讀寫和協議解析,執行命令還是使用單線程,所以是不會有線程安全的問題。
之所以加入了多線程因爲 redis 的性能瓶頸在於網絡 IO 而非 CPU,使用多線程能提升 IO 讀寫的效率,從而整體提高 redis 的性能。
5.redis 的持久化機制有哪些?優缺點說說
redis 有兩種持久化的方式,AOF 和 RDB.
AOF:
- redis 每次執行一個命令時, 都會把這個「命令原本的語句記錄到一個. aod 的文件當中, 然後通過 fsync 策略, 將命令執行後的數據持久化到磁盤中」(不包括讀命令),
AOF 的優缺點
-
AOF 的「優點」:
-
1.AOF 可以「更好的保護數據不丟失」,一般 AOF 會以每隔 1 秒,通過後臺的一個線程去執行一次 fsync 操作,如果 redis 進程掛掉,最多丟失 1 秒的數據
-
2.AOF 是將命令直接追加在文件末尾的,「寫入性能非常高」
-
3.AOF 日誌文件的命令通過非常可讀的方式進行記錄,這個非常「適合做災難性的誤刪除緊急恢復」,如果某人不小心用 flushall 命令清空了所有數據,只要這個時候還沒有執行 rewrite,那麼就可以將日誌文件中的 flushall 刪除,進行恢復
-
AOF 的「缺點」:
-
- 對於同一份數據源來說, 一般情況下 AOF 文件比 RDB 數據快照要大
-
- 由於 .aof 的每次命令都會寫入, 那麼相對於 RDB 來說「需要消耗的性能也就更多」,當然也會有 aof 重寫將 aof 文件優化。
-
- 「數據恢復比較慢」,不適合做冷備。
RDB:
- 把某個時間點 redis 內存中的數據以二進制的形式存儲的一個. rdb 爲後綴的文件當中, 也就是「週期性的備份 redis 中的整個數據」, 這是 redis 默認的持久化方式, 也就是我們說的快照 (snapshot),是採用 fork 子進程的方式來寫時同步的。
RDB 的優缺點
-
RDB 的優點:
-
- 它是將某一時間點 redis 內的所有數據保存下來, 所以當我們做「大型的數據恢復時, RDB 的恢復速度會很快」
-
- 由於 RDB 的 FROK 子進程這種機制, 隊友給客戶端提供讀寫服務的影響會非常小
-
RDB 的缺點:
-
舉個例子假設我們定時 5 分鐘備份一次, 在 10:00 的時候 redis 備份了數據, 但是如果在 10:04 的時候服務掛了, 那麼我們就會丟失在 10:00 到 10:04 的整個數據
-
1:「有可能會產生長時間的數據丟失」
-
2: 可能會有長時間停頓: 我們前面講了, fork 子進程這個過程是和 redis 的數據量有很大關係的, 如果「數據量很大, 那麼很有可能會使 redis 暫停幾秒」
6. Redis 的過期鍵的刪除策略有哪些?
過期策略通常有以下三種:
-
定時過期:每個設置過期時間的 key 都需要創建一個定時器,到過期時間就會立即清除。該策略可以立即清除過期的數據,對內存很友好;但是會佔用大量的 CPU 資源去處理過期的數據,從而影響緩存的響應時間和吞吐量。
-
惰性過期:只有當訪問一個 key 時,纔會判斷該 key 是否已過期,過期則清除。該策略可以最大化地節省 CPU 資源,卻對內存非常不友好。極端情況可能出現大量的過期 key 沒有再次被訪問,從而不會被清除,佔用大量內存。
-
定期過期:每隔一定的時間,會掃描一定數量的數據庫的 expires 字典中一定數量的 key,並清除其中已過期的 key。該策略是前兩者的一個折中方案。通過調整定時掃描的時間間隔和每次掃描的限定耗時,可以在不同情況下使得 CPU 和內存資源達到最優的平衡效果。
7. Redis 的內存滿了怎麼辦?
實際上 Redis 定義了「8 種內存淘汰策略」用來處理 redis 內存滿的情況:
-
1.noeviction:直接返回錯誤,不淘汰任何已經存在的 redis 鍵
-
2.allkeys-lru:所有的鍵使用 lru 算法進行淘汰
-
3.volatile-lru:有過期時間的使用 lru 算法進行淘汰
-
4.allkeys-random:隨機刪除 redis 鍵
-
5.volatile-random:隨機刪除有過期時間的 redis 鍵
-
6.volatile-ttl:刪除快過期的 redis 鍵
-
7.volatile-lfu:根據 lfu 算法從有過期時間的鍵刪除
-
8.allkeys-lfu:根據 lfu 算法從所有鍵刪除
8.Redis 的熱 key 問題怎麼解決?
熱 key 就是說,在某一時刻,有非常多的請求訪問某個 key,流量過大,導致該 redi 服務器宕機
解決方案:
-
可以將結果緩存到本地內存中
-
將熱 key 分散到不同的服務器中
-
設置永不過期
9. 緩存擊穿、緩存穿透、緩存雪崩是什麼?怎麼解決呢?
緩存穿透:
- 緩存穿透是指用戶請求的數據在緩存中不存在並且在數據庫中也不存在,導致用戶每次請求該數據都要去數據庫中查詢一遍,然後返回空。
解決方案:
-
布隆過濾器
-
返回空對象
緩存擊穿:
- 緩存擊穿,是指一個 key 非常熱點,在不停的扛着大併發,大併發集中對這一個點進行訪問,當這個 key 在失效的瞬間,持續的大併發就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞。
解決方案:
-
互斥鎖
-
永不過期
緩存雪崩:
- 緩存雪崩是指緩存中不同的數據大批量到過期時間,而查詢數據量巨大,請求直接落到數據庫上導致宕機。
解決方案:
-
均勻過期
-
加互斥鎖
-
緩存永不過期
-
雙層緩存策略
10.Redis 有哪些部署方式?
-
單機模式: 這也是最基本的部署方式, 只需要一臺機器, 負責讀寫, 一般只用於開發人員自己測試
-
哨兵模式: 哨兵模式是一種特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一個獨立的進程,作爲進程,它會獨立運行。其原理是哨兵通過發送命令,等待 Redis 服務器響應,從而監控運行的多個 Redis 實例。它具備自動故障轉移、集羣監控、消息通知等功能。
-
cluster 集羣模式: 在 redis3.0 版本中支持了 cluster 集羣部署的方式,這種集羣部署的方式能自動將數據進行分片,每個 master 上放一部分數據,提供了內置的高可用服務,即使某個 master 掛了,服務還可以正常地提供。
-
主從複製: 在主從複製這種集羣部署模式中,我們會將數據庫分爲兩類,第一種稱爲主數據庫 (master),另一種稱爲從數據庫 (slave)。主數據庫會負責我們整個系統中的讀寫操作,從數據庫會負責我們整個數據庫中的讀操作。其中在職場開發中的真實情況是,我們會讓主數據庫只負責寫操作,讓從數據庫只負責讀操作,就是爲了讀寫分離,減輕服務器的壓力。
11. 哨兵有哪些作用?
-
- 監控整個主數據庫和從數據庫,觀察它們是否正常運行
-
- 當主數據庫發生異常時,自動的將從數據庫升級爲主數據庫,繼續保證整個服務的穩定
12. 哨兵選舉過程是怎麼樣的?
-
- 第一個發現該 master 掛了的哨兵,向每個哨兵發送命令,讓對方選舉自己成爲領頭哨兵
-
- 其他哨兵如果沒有選舉過他人,就會將這一票投給第一個發現該 master 掛了的哨兵
-
- 第一個發現該 master 掛了的哨兵如果發現由超過一半哨兵投給自己,並且其數量也超過了設定的 quoram 參數,那麼該哨兵就成了領頭哨兵
-
- 如果多個哨兵同時參與這個選舉,那麼就會重複該過程,知道選出一個領頭哨兵
選出領頭哨兵後,就開始了故障修復,會從選出一個從數據庫作爲新的 master
13.cluster 集羣模式是怎麼存放數據的?
一個 cluster 集羣中總共有 16384 個節點,集羣會將這 16384 個節點平均分配給每個節點,當然,我這裏的節點指的是每個主節點,就如同下圖:
14.cluster 的故障恢復是怎麼做的?
判斷故障的邏輯其實與哨兵模式有點類似,在集羣中,每個節點都會定期的向其他節點發送 ping 命令,通過有沒有收到回覆來判斷其他節點是否已經下線。
如果長時間沒有回覆,那麼發起 ping 命令的節點就會認爲目標節點疑似下線,也可以和哨兵一樣稱作主觀下線,當然也需要集羣中一定數量的節點都認爲該節點下線纔可以,我們來說說具體過程:
-
- 當 A 節點發現目標節點疑似下線,就會向集羣中的其他節點散播消息,其他節點就會向目標節點發送命令,判斷目標節點是否下線
-
- 如果集羣中半數以上的節點都認爲目標節點下線,就會對目標節點標記爲下線,從而告訴其他節點,讓目標節點在整個集羣中都下線
15. 主從同步原理是怎樣的?
-
- 當一個從數據庫啓動時,它會向主數據庫發送一個 SYNC 命令,master 收到後,在後臺保存快照,也就是我們說的 RDB 持久化,當然保存快照是需要消耗時間的,並且 redis 是單線程的,在保存快照期間 redis 受到的命令會緩存起來
-
- 快照完成後會將緩存的命令以及快照一起打包發給 slave 節點,從而保證主從數據庫的一致性。
-
- 從數據庫接受到快照以及緩存的命令後會將這部分數據寫入到硬盤上的臨時文件當中,寫入完成後會用這份文件去替換掉 RDB 快照文件,當然,這個操作是不會阻塞的,可以繼續接收命令執行,具體原因其實就是 fork 了一個子進程,用子進程去完成了這些功能。
因爲不會阻塞,所以,這部分初始化完成後,當主數據庫執行了改變數據的命令後,會異步的給 slave,這也就是我們說的複製同步階段,這個階段會貫穿在整個中從同步的過程中,直到主從同步結束後,複製同步纔會終止。
16. 無硬盤複製是什麼?
我們剛剛說了主從之間是通過 RDB 快照來交互的,雖然看來邏輯很簡單,但是還是會存在一些問題,但是會存在着一些問題。
-
- master 禁用了 RDB 快照時,發生了主從同步 (複製初始化) 操作,也會生成 RDB 快照,但是之後如果 master 發成了重啓,就會用 RDB 快照去恢復數據,這份數據可能已經很久了,中間就會丟失數據
-
- 在這種一主多從的結構中,master 每次和 slave 同步數據都要進行一次快照,從而在硬盤中生成 RDB 文件,會影響性能
爲了解決這種問題,redis 在後續的更新中也加入了無硬盤複製功能,也就是說直接通過網絡發送給 slave,避免了和硬盤交互,但是也是有 io 消耗
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/OATg5_H-E3_BN7qcxjVrdg