常見的Redis面試題及分析
常見的Redis面試題及分析
經常問到的Redis問題。
1 什麼是redis?
Redis 是一個基於記憶體的高效能key-value資料庫。
2. Memcache與Redis的區別都有哪些?
1)儲存方式
Memecache把資料全部存在記憶體之中,斷電後會掛掉,資料不能超過記憶體大小。
Redis可以把資料儲存在硬碟上,用來保證資料的永續性。
2)資料型別
Memcache的資料型別比較簡單。
Redis有複雜的資料型別。
3)使用底層模型不同
它們之間底層的實現方式 以及與客戶端之間通訊的應用協議不一樣。
4)value大小
redis最大可以達到1GB,而memcache只有1MB
3.Redis有哪些資料結構?
字串String、字典Hash、列表List、集合Set、有序集合SortedSet。
更進一步,redis還有資料結構HyperLogLog、Geo、Pub/Sub、BloomFilter,RedisSearch,Redis-ML等
4.為什麼redis需要把所有資料放到記憶體中?
Redis為了達到最快的讀寫速度,將資料都讀到記憶體中,並通過非同步的方式將資料寫入磁碟。所以redis具有快速和資料持久化的特徵。
如果不將資料放在記憶體中,磁碟I/O速度為嚴重影響redis的效能。
如果設定了最大使用的記憶體,則資料量達到記憶體限值後,將不能繼續插入新值。
5.怎麼用Redis建立分散式鎖
先用setnx來爭搶鎖,搶到之後,再用expire給鎖加一個過期時間防止鎖忘記了釋放。
注意:如果在setnx之後,並且在執行expire之前,程序意外崩潰或者要重啟維護了,這個鎖就永遠得不到釋放了。
為了解決這個問題,set指令有非常複雜的引數,可以同時把setnx和expire合成一條指令
6.假如Redis裡面有1億個key,其中有10萬個key是以固定的字首開頭的,如何將這些全部找出來?
使用keys命令可以掃出指定模式的key列表。
但是,如果這個redis正在給線上的業務提供服務,因為redis的單執行緒的,所以keys命令會導致執行緒阻塞一段時間,線上服務會停頓,直到命令執行完畢,服務才能恢復。
為了解決這個問題,可以使用scan命令,scan命令可以無阻塞的提取出指定模式的key列表,會有一定的重複概率,在客戶端做一次去重就可以了,但是整體所花費的時間會比直接用keys命令長。
7.如果有大量的key需要設定同一時間過期,需要如何處理?
如果大量的key過期時間設定的過於集中,那麼當到了過期的那個時間點,redis可能會出現短暫的卡頓。
這種情況下,可以在時間上加一個隨機值,使得過期時間分散一些。
8.Redis如何做持久化的?
bgsave做映象全量持久化,aof做增量持久化。
因為bgsave會耗費較長時間,達不到實時,在停機的時候會導致大量丟失資料,所以需要aof來配合使用。
如果不要求效能,在每條寫指令時都sync一下磁碟,就不會丟失資料。但是在高效能的要求下每次都sync是不現實的,一般都使用定時sync,比如1秒1次,這個時候最多會丟失1s的資料。
Redis會定期做aof重寫,壓縮aof檔案日誌大小。
在redis例項重啟時,優先使用aof來恢復記憶體的狀態,如果沒有aof日誌,就會使用rdb檔案來恢復。
9.講一下對Redis的同步機制的理解
Redis可以使用主從同步,從從同步。
第一次同步時,主節點做一次bgsave,並同時將後續修改操作記錄到記憶體buffer,待完成後將rdb檔案全量同步到複製節點,複製節點接受完成後將rdb映象載入到記憶體。
載入完成後,再通知主節點將期間修改的操作記錄同步到複製節點進行重放就完成了同步過程。
10 對Redis的回收策略的理解
volatile-lru:從已設定過期時間的資料集(server.db[i].expires)中挑選最近最少使用的資料淘汰
volatile-ttl:從已設定過期時間的資料集(server.db[i].expires)中挑選將要過期的資料淘汰
volatile-random:從已設定過期時間的資料集(server.db[i].expires)中任意選擇資料淘汰
allkeys-lru:從資料集(server.db[i].dict)中挑選最近最少使用的資料淘汰
allkeys-random:從資料集(server.db[i].dict)中任意選擇資料淘汰
no-enviction(驅逐):禁止驅逐資料
11 對多級快取的理解?
多級快取就是有多個快取,將ehcache配合redis快取,比如ehcache作為1級快取,使用redis作為2級快取。
12 如何解決DB和快取一致性問題?
當修改了資料庫後,沒有及時修改快取就會造成不一致的情況。
而修改快取失敗的情況,最主要的原因就是快取伺服器掛了。
如果因為網路問題引起的沒有及時更新,可以通過重試機制來解決。
然而如果快取伺服器死了,那麼客戶端的請求自然也就無法到達,從而請求會直接打到資料庫。
因此,我們在修改資料庫後,無法修改快取,那麼其中一個方案可以將這條資料放到資料庫中,同時啟動一個非同步任務,定時去檢測快取伺服器是否連線成功,一旦連線成功則從資料庫中按順序取出未同步的資料,依次進行同步快取。
13.如何解決快取穿透
生產中,通常都是先檢查快取中是否存在,如果存在直接返回快取中內容,如果不存在就直接查詢資料庫,然後再快取查詢結果並返回。
這個時候如果查詢的某一個數據在快取中一直不存在,就會造成每一次請求都查詢DB,這樣快取就失去了作用,在流量大時,就造成了快取穿透。
有一個解決方案,可以將這個不存在的key預先設定一個值。是將快取的KEY預先設定一個值,如,"key":"&&"。
如果查詢請求過來,得到的返回值是發現是預先設定的"&&", 那我們的應用就可以決定是否繼續等待繼續訪問,還是放棄掉這次操作。
如果繼續等待訪問,過一個時間輪詢點後,再次請求這個key,如果取到的值不再是"&&",則認為這時候key有值了,從而把大量的類似請求阻擋在快取之中,也就避免了快取穿透。
13. redis常見效能問題和解決方案
(1) Master最好不要做任何持久化工作,如RDB記憶體快照和AOF日誌檔案
(2) 如果資料比較重要,某個Slave開啟AOF備份資料,策略設定為每秒同步一次
(3) 為了主從複製的速度和連線的穩定性,Master和Slave最好在同一個區域網內
(4) 儘量避免在壓力很大的主庫上增加從庫
(5) 主從複製不要用圖狀結構,用單向連結串列結構更為穩定,即:Master <- Slave1 <- Slave2 <- Slave3...
這樣的結構方便解決單點故障問題,實現Slave對Master的替換。如果Master掛了,可以立刻啟用Slave1做Mas