面試準備:Redis常見面試題彙總

1.介紹一下Redis

Redis 是一款使用 C 語言編寫的高性能 key-value 數據庫

特點:

  • 性能極高,能到 100000 次/s 讀寫速度
  • 支持數據的持久化,對數據的更新採用Copy-on-write技術,可以異步地保存到磁盤上
  • 豐富的數據類型,String(字符串)、List(列表)、Hash(字典)、Set(集合)、Sorted Set(有序集合)
  • 原子性:Redis 的所有操作都是原子性的,多個操作通過 MULTI 和 EXEC 指令支持事務
  • 豐富的特性:key 過期、publish/subscribe、notify
  • 支持數據的備份,快速的主從複製
  • 節點集羣,很容易將數據分佈到多個Redis實例中
  • 單線程:避免了不必要的上下文切換和競爭條件

用途:
高速緩存。
分佈式鎖。
單點登錄共享session。
計數器。

2.Redis爲什麼這麼快?

1、完全基於內存,絕大部分請求是純粹的內存操作,非常快速。數據存在內存中,類似於HashMap,HashMap的優勢就是查找和操作的時間複雜度都是O(1);

2、數據結構簡單高效,如 Hash、跳錶等。

3、採用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因爲可能出現死鎖而導致的性能消耗;

4、使用多路I/O複用模型,非阻塞IO

5、使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis直接自己構建了VM 機制 ,因爲一般的系統調用系統函數的話,會浪費一定的時間去移動和請求;

3.Redis支持哪些數據類型?

Redis 支持五種數據類型

string:字符串
hash:哈希
list:列表
set:集合
sorted set:有序集合

4.Redis與Memcached的區別?

暫不做了解。

5.Redis跳錶是什麼?

跳躍表基於有序單鏈表,在鏈表的基礎上,每個結點不只包含一個指針,還可能包含多個指向後繼結點的指針,這樣就可以跳過一些不必要的結點,從而加快查找、刪除等操作。
在這裏插入圖片描述

6.什麼是冷熱數據分離?什麼是VM機制?

Redis使用到了VM, 通過VM功能可以實現冷熱數據分離。使熱數據仍在內存中,冷數據保存到磁盤。這樣就可以避免因爲內存不足而造成訪問速度下降的問題。

冷數據即是那些不經常訪問、但又無法刪除的信息。

7.Redis過期鍵的刪除策略有哪些?

惰性刪除:不主動刪除過期鍵,從鍵空間中獲取鍵時,都檢查取得的鍵是否過期,過期則刪除;沒過期則返回
定期刪除:每隔一段時間對數據庫進行一次檢查,刪除裏面的過期鍵。刪除多少過期鍵、檢查多少個數據庫,由算法決定。

參考:Java架構直通車——Redis緩存過期處理與內存淘汰機制

8.說說Redis的同步機制?

2.8 版以前

Redis 通過同步(sync)和指令傳播(command propagate)兩個操作完成同步

同步(sync):將從節點的數據庫狀態更新至與主節點的數據庫狀態一致

從節點向主節點發送 SYNC 指令
收到 SYNC 指令,主節點執行 BGSAVE 指令,在後臺生成一個 RDB 文件,並使用一個緩衝區記錄從現在開始執行的所有寫指令
主節點 BGSAVE 指令執行後,會將生成的 RDB 文件發送給從節點
從節點接收、載入 RDB 文件,將數據庫狀態更新至主節點執行 BGSAVE 指令時的數據庫狀態
從節點加載完 RDB 文件,通知主節點將記錄在緩衝區裏面的所有寫指令發送給從節點,從節點執行這些寫指令,將數據庫狀態更新至主節點當前數據庫狀態

指令傳播(command propagate):主節點數據被修改,會主動向從節點發送執行的寫指令,從節點執行之後,兩個節點數據狀態又保持一致

爲了解決主從節點斷線複製低效的問題(SYNC過程中生成、傳輸、載入 RDB 文件耗費大量 CPU、內存、磁盤 IO 資源),2.8 版開始新增 PSYNC 指令。

PSYNC 具有兩種模式

完整重同步(full resynchronization),與SYNC過程基本一致
部分重同步(partial resynchronization),藉助複製偏移量、複製積壓緩衝區、服務器運行 ID ,完成主從節點斷開連接後,從節點重連主節點後,條件允許,主節點將連接斷開期間執行的寫指令發送給從節點,從節點接收並執行寫指令,將數據庫更新至主節點當前狀態

9.Pipeline有什麼好處?

多個指令之間沒有依賴關係,可以使用 pipeline 一次性執行多個指令,減少 IO,縮減時間。

10.Redis實現分佈式鎖?

參考:Java架構直通車——基於Redis的Set NX實現分佈式鎖

11.Redis實現冪等性?

爲需要保證冪等性的每一次請求創建一個唯一標識token, 先獲取token, 並將此token存入redis, 請求接口時, 將此token放到header或者作爲請求參數請求接口, 後端接口判斷redis中是否存在此token:

如果存在, 正常處理業務邏輯, 並從redis中刪除此token, 那麼, 如果是重複請求, 由於token已被刪除, 則不能通過校驗, 返回請勿重複操作提示。

12. 接觸過哪些Redis客戶端?

Redisson

優點:

實現了分佈式特性和可擴展的 Java 數據結構,適合分佈式開發
API 線程安全
基於 Netty 框架的事件驅動的通信,可異步調用
缺點:

API 更抽象,學習使用成本高

Jedis

優點:

提供了比較全面的 Redis 操作特性的 API
API 基本與 Redis 的指令一一對應,使用簡單易理解
缺點:

同步阻塞 IO
不支持異步
線程不安全

Lettuce

優點:

線程安全
基於 Netty 框架的事件驅動的通信,可異步調用
適用於分佈式緩存
缺點:

API 更抽象,學習使用成本高

13.Redis哈希槽?

Redis 集羣沒有使用一致性 hash,而是引入了哈希槽的概念。

Redis 集羣有 16384 個哈希槽,每個 key 通過 CRC16 算法計算的結果,對 16384 取模後放到對應的編號在 0-16383 之間的哈希槽,集羣的每個節點負責一部分哈希槽

14.Redis 集羣會有寫操作丟失嗎?

以下情況可能導致寫操作丟失:

過期 key 被清理
最大內存不足,導致 Redis 自動清理部分 key 以節省空間
主庫故障後自動重啓,從庫自動同步
單獨的主備方案,網絡不穩定觸發哨兵的自動切換主從節點,切換期間會有數據丟失

15.如何保證Redis中存的都是熱點數據?

Redis存儲在內存中的數據升到配置大小時,就進行數據淘汰

使用 allkeys-lru 策略,從數據集(server.db[i].dict)中挑選最近最少使用的數據優先淘汰,即可滿足保存熱點數據

16.緩存穿透、擊穿、雪崩?

參考:Java架構直通車——Redis緩存穿透/擊穿/雪崩

17.熱點key?

緩存中的某些Key(可能對應用與某個促銷商品)對應的value存儲在集羣中一臺機器,使得所有流量涌向同一機器,成爲系統的瓶頸,該問題的挑戰在於它無法通過增加機器容量來解決。(當key失效的時候,大量的線程構建緩存,導致負載增加)

解決方案:

  1. 客戶端熱點key緩存:將熱點key對應value並緩存在客戶端本地,並且設置一個失效時間。對於每次讀請求,將首先檢查key是否存在於本地緩存中,如果存在則直接返回,如果不存在再去訪問分佈式緩存的機器。
  2. 將熱點key分散爲多個子key,然後存儲到緩存集羣的不同機器上,這些子key對應的value都和熱點key是一樣的。當通過熱點key去查詢數據時,通過某種hash算法隨機選擇一個子key,然後再去訪問緩存機器,將熱點分散到了多個子key上。
  3. 爲每個 value 設置一個邏輯過期時間,當發現超過邏輯過期時間後,會使用單獨的線程去構建緩存。緩存層面沒有設置過期時間(這種方案可以解決大量線程等待的問題,但它可能導致數據不一致的問題)
  4. 針對熱點key失效,大量線程構建緩存(使用分佈式鎖,只讓一個線程構建緩存,可以解決這個問題)。

18.大Key(Big Key)?

Redis使用過程中經常會有各種大key的情況, 比如單個簡單的key存儲的value很大。
由於redis是單線程運行的,如果一次操作的value很大會對整個redis的響應時間造成負面影響,導致IO網絡擁塞。

解決:

將整存整取的大對象,分拆爲多個小對象。可以嘗試將對象分拆成幾個key-value, 使用multiGet獲取值,這樣分拆的意義在於分拆單次操作的壓力,將操作壓力平攤到多個redis實例中,降低對單個redis的IO影響;

19.無底洞問題?

暫時不做了解。

20.緩存與數據庫一致性問題?

參考:緩存架構
參考:分佈式DB與Cache一致性

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章