常見的Redis面試“刁難”問題
Redis有哪些資料結構?
字元串String、字典Hash、清單List、集合Set、有序集合SortedSet。
如果你是Redis中進階使用者,還需要加上下面幾種資料結構HyperLogLog、Geo、Pub/Sub。
如果你說還玩過Redis Module,像BloomFilter,RedisSearch,Redis-ML,面試官得眼睛就開始發亮了。
使用過Redis分布式鎖麼,它是什麼回事?
先拿setnx來争搶鎖,搶到之後,再用expire給鎖加一個過期時間防止鎖忘記了釋放。
這時候對方會告訴你說你回答得不錯,然後接着問如果在setnx之後執行expire之前程序意外crash或者要重新開機維護了,那會怎麼樣?
這時候你要給予驚訝的回報:唉,是喔,這個鎖就永遠得不到釋放了。緊接着你需要抓一抓自己得腦袋,故作思考片刻,好像接下來的結果是你主動思考出來的,然後回答:我記得set指令有非常複雜的參數,這個應該是可以同時把setnx和expire合成一條指令來用的!對方這時會顯露笑容,心裡開始默念:摁,這小子還不錯。
假如Redis裡面有1億個key,其中有10w個key是以某個固定的已知的字首開頭的,如果将它們全部找出來?
使用keys指令可以掃出指定模式的key清單。
對方接着追問:如果這個redis正在給線上的業務提供服務,那使用keys指令會有什麼問題?
這個時候你要回答redis關鍵的一個特性:redis的單線程的。keys指令會導緻線程阻塞一段時間,線上服務會停頓,直到指令執行完畢,服務才能恢複。這個時候可以使用scan指令,scan指令可以無阻塞的提取出指定模式的key清單,但是會有一定的重複機率,在用戶端做一次去重就可以了,但是整體所花費的時間會比直接用keys指令長。
使用過Redis做異步隊列麼,你是怎麼用的?
一般使用list結構作為隊列,rpush生産消息,lpop消費消息。當lpop沒有消息的時候,要适當sleep一會再重試。
如果對方追問可不可以不用sleep呢?list還有個指令叫blpop,在沒有消息的時候,它會阻塞住直到消息到來。
如果對方追問能不能生産一次消費多次呢?使用pub/sub主題訂閱者模式,可以實作1:N的消息隊列。
如果對方追問pub/sub有什麼缺點?在消費者下線的情況下,生産的消息會丢失,得使用專業的消息隊列如rabbitmq等。
如果對方追問redis如何實作延時隊列?我估計現在你很想把面試官一棒打死如果你手上有一根棒球棍的話,怎麼問的這麼詳細。但是你很克制,然後神态自若的回答道:使用sortedset,拿時間戳作為score,消息内容作為key調用zadd來生産消息,消費者用zrangebyscore指令擷取N秒之前的資料輪詢進行處理。
到這裡,面試官暗地裡已經對你豎起了大拇指。但是他不知道的是此刻你卻豎起了中指,在椅子背後。
如果有大量的key需要設定同一時間過期,一般需要注意什麼?
如果大量的key過期時間設定的過于集中,到過期的那個時間點,redis可能會出現短暫的卡頓現象。一般需要在時間上加一個随機值,使得過期時間分散一些。
Redis如何做持久化的?
bgsave做鏡像全量持久化,aof做增量持久化。因為bgsave會耗費較長時間,不夠實時,在停機的時候會導緻大量丢失資料,是以需要aof來配合使用。在redis執行個體重新開機時,優先使用aof來恢複記憶體的狀态,如果沒有aof日志,就會使用rdb檔案來恢複。
如果再問aof檔案過大恢複時間過長怎麼辦?你告訴面試官,Redis會定期做aof重寫,壓縮aof檔案日志大小。如果面試官不夠滿意,再拿出殺手锏答案,Redis4.0之後有了混合持久化的功能,将bgsave的全量和aof的增量做了融合處理,這樣既保證了恢複的效率又兼顧了資料的安全性。這個功能甚至很多面試官都不知道,他們肯定會對你刮目相看。
如果對方追問那如果突然機器掉電會怎樣?取決于aof日志sync屬性的配置,如果不要求性能,在每條寫指令時都sync一下磁盤,就不會丢失資料。但是在高性能的要求下每次都sync是不現實的,一般都使用定時sync,比如1s1次,這個時候最多就會丢失1s的資料。
Pipeline有什麼好處,為什麼要用pipeline?
可以将多次IO往返的時間縮減為一次,前提是pipeline執行的指令之間沒有因果相關性。使用redis-benchmark進行壓測的時候可以發現影響redis的QPS峰值的一個重要因素是pipeline批次指令的數目。
Redis的同步機制了解麼?
Redis可以使用主從同步,從從同步。第一次同步時,主節點做一次bgsave,并同時将後續修改操作記錄到記憶體buffer,待完成後将rdb檔案全量同步到複制節點,複制節點接受完成後将rdb鏡像加載到記憶體。加載完成後,再通知主節點将期間修改的操作記錄同步到複制節點進行重放就完成了同步過程。
是否使用過Redis叢集,叢集的原理是什麼?
Redis Sentinal着眼于高可用,在master當機時會自動将slave提升為master,繼續提供服務。
Redis Cluster着眼于擴充性,在單個redis記憶體不足時,使用Cluster進行分片存儲。