18 道 Redis 面試題

學習是一條漫長之路

  • 什麼是Redis?
    Redis 全稱 Remote Dictionary Server 遠程字典服務,是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持續化的日誌型、Key-Value 數據庫,並提供多種語言的API。
  • Redis 相比 memcached 有哪些優勢?
    1. memcached 所有的值均是簡單的字符串,redis 作爲其代替者,支持更爲豐富的數據類型。
    2. redis 的速度比 memcached 快得多。
    3. redi 可以支持持久化數據
  • Redis 支持幾種數據類型?以及每種數據類型的使用場景?
    1. String 字符串——這個其實沒啥好說的,最常規的set/get操作,value可以是String也可以是數字。一般做一些複雜的計數功能的緩存。
    2. Hash 哈希——這裏value存放的是結構化的對象,比較方便的就是操作其中的某個字段。博主在做單點登錄的時候,就是用這種數據結構存儲用戶信息,以cookieId作爲key,設置30分鐘爲緩存過期時間,能很好的模擬出類似session的效果。
    3. List 列表——使用List的數據結構,可以做簡單的消息隊列的功能。另外還有一個就是,可以利用lrange命令,做基於redis的分頁功能,性能極佳,用戶體驗好。本人還用一個場景,很合適—取行情信息。就也是個生產者和消費者的場景。LIST可以很好的完成排隊,先進先出的原則。
    4. Set 集合——因爲set堆放的是一堆不重複值的集合。所以可以做全局去重的功能。爲什麼不用JVM自帶的Set進行去重?因爲我們的系統一般都是集羣部署,使用JVM自帶的Set,比較麻煩,難道爲了一個做一個全局去重,再起一個公共服務,太麻煩了。另外,就是利用交集、並集、差集等操作,可以計算共同喜好,全部的喜好,自己獨有的喜好等功能。
    5. sorted set 有序集合——sorted set多了一個權重參數score,集合中的元素能夠按score進行排列。可以做排行榜應用,取TOP N操作。
  • Redis 主要消耗什麼物理資源?
    內存
  • Redis 有哪幾種數據淘汰策略?
    1. volatile-lru:從設置了過期時間的數據集中,選擇最近最久未使用的數據釋放。
    2. allkeys-lru:從數據集中(包括設置過期時間以及未設置過期時間的數據集中),選擇最近最久未使用的數據釋放。
    3. volatile-random:從設置了過期時間的數據集中,隨機選擇一個數據進行釋放。
    4. allkeys-random:從數據集中(包括了設置過期時間以及爲設置過期時間)隨機選擇一個數據進行釋放。
    5. volatile-ttl:從設置了過期時間的數據集中,選擇馬上就要過期的數據進行釋放操作。
    6. noevication:不刪除任意數據(但 redis 還會根據引用計數器進行釋放),這時如果內存不夠,會直接返回錯誤。
  • Redis 集羣方案應該怎麼做?都有那些方案?
    1. 客戶端分片
    2. 基於代理的分片
    3. 路由查詢
  • Redis 有哪些適合的場景?
    1. 會話緩存 (Session Cache)
    2. 全頁緩存(FPC)
    3. 隊列
    4. 排行榜、計數器
    5. 發佈、訂閱
  • Redis 支持的Java客戶端都有哪些?官方推薦使用哪個?
    Redisson、Jedis、lettuce等等,官方推薦使用 Redisson
  • 你知道有哪些 Redis 分區實現方案?
    1. 客戶端分區
      就是由客戶端自己決定要將 key 存放在哪個實例,再去哪個實力獲取
    2. 代理分區
      客戶端依賴一個代理,代理決定去哪個節點寫數據或者讀數據。代理根據分區規則決定請求哪些 Redis 實例,然後根據 Redis 的響應結果返回給客戶端。Redis 和 memcached 的一種代理實現就是 Twemproxy
    3. 查詢路由
      客戶端隨機的請求任意一個 redis 實例,然後由 Redis 將請求轉發給正確的 Redis 節點
  • Redis 分區有什麼缺點?
    多鍵操作是不被支持的
    當應用分區的時候,數據的處理非常複雜
    分區的最小粒度是鍵,因此我們不能將關聯到一個鍵的很大的數據集映射到不同的實例
  • 分佈式 Redis 是前期做還是後期規模上來了再做好?爲什麼?
    爲防止以後的擴容,最好的辦法就是一開始就啓動較多實例。
  • Redis 與其他 key-value 存儲有什麼不同?
    • Redis 有着更爲複雜的數據結構並且提供對他們的原子性操作,這是一個不同於其他數據庫的進化路徑,Redis 的數據類型都是基於基本數據結構的同時對程序眼透明,無需進行額外的抽象。
    • Redis 運行在內存中但是可以不用持久化到磁盤,所以在對不用數據集進行高速讀寫時需要權衡內存,因爲數據量不能大於硬件內存,在內存數據庫方面的另一個有點是:相比在磁盤上相同的複雜的數據結構,在內存中操作起來非常簡單,這樣Redis 可以做很多內部複雜性很強的事情,同時,在磁盤格式方面他們是緊湊的以追加的方式產生的,因爲他們並不需要進行隨機訪問。
  • Redis 常見性能問題和解決方案?
    1. Master 最好不要做任何持久化工作,如 RDB 內存快照和 AOF 日誌文件
    2. 如果數據比較重要,某個 Slave 開啓AOF 備份數據,策略設置爲每秒同步一次
    3. 爲了主從複製的速度和連接的穩定性,Master和Slave最好在同一個局域網內
    4. 儘量避免在壓力很大的主庫上增加從庫
    5. 主從複製不要用圖狀結構,用單向鏈表結構更爲穩定,即:Master < Slave1 < Slave2 < Slave3 … 這樣的結構方便解決單點故障問題,實現 Slave 對 Master 的替換,如果 Master 掛了,可以立刻啓動 Slave1 做 Master ,其他不變。
  • 修改配置不重啓 Redis 會實時生效嗎?
    一般不需要重啓。
  • 單線程的 redis 爲什麼這麼快?
    1. 純內存操作
    2. 單線程操作,避免了頻繁的上下文切換
    3. 採用了非阻塞 I/O 多路複用機制
  • 爲什麼 Redis 的操作是原子性的,怎麼保證原子性的?
    1. 對於 Redis 而言,命令的原子性指的是:一個操作的不可再分,操作要麼執行,要麼不執行。
    2. Redis 的操作之所以是原子性的,是因爲 Redis 是單線程的。
    3. Redis 本身提供的所有 API 都是原子操作,Redis 中的事務其實是要保證批量操作的原子性。
    4. 多個命令在併發中也是原子性的嗎?不一定,將get和set改爲單命令操作,incr,使用Redis 的事務,或者使用 Redis + Lua 的方式實現。
  • 講講Redis 事務
    Redis 事務功能通過MULTI、EXEC、DISCARD和WATCH 四個原語實現的。Redis 會將一個事務中的所有命令序列化,然後按照順序執行。
    1. redis 不支持回滾,“Redis 在事務失敗時不進行回滾,而是繼續執行餘下的命令”,所以 Redis 的內部可以保持簡單且快速。
    2. 如果在一個事務中的命令出現錯誤,那麼所有的命令都不會執行。
    3. 如果在一個事務中出現運行錯誤,那麼正確的命令會被i執行。
  1. MULTI命令用於開啓一個事務,它總是返回OK,MULTI執行之後,客戶端可以繼續向服務器發送任意多條命令,這些命令不會立即被執行,而是被放到一個隊列中,當 EXEC命令被調用時,所有隊列中的命令纔會被執行。
  2. EXEC:執行所有事務快內的命令,返回事務塊的所有命令的返回值,按命令執行的先後順序排列。當操作被打斷時,返回空值 null。
  3. 通過調用DISCARD,客戶端可以清空事務隊列,並放棄執行事務,並且客戶端會從事務狀態中退出。
  4. WATCH命令可以爲 Redis 事務提供 check-and set (CAS)行爲,可以監控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之後的事務就不會執行,監控一直持續到EXEC命令。
  • Redis 實現分佈式鎖?
    Redis 爲單進程單線程模式,採用隊列模式將併發訪問變爲串行訪問,且多客戶端對 Redis 的連接並不存在競爭關係 Redis 中可以使用 SETN 命令實現分佈式鎖。
    將 key 的值設爲 value ,當且僅當 key 不存在,若給定的 key 已經存在,則 SETNX 不做任何動作
    解鎖:使用 del key 命令就能釋放鎖
    解決死鎖:
    1. 通過 Redis 中 expire() 給鎖設定最大持有時間,如果超時,則 Redis 來幫我們釋放鎖。
    2. 使用 setnx key “當前系統時間+鎖持有時間” 和 getset key “當前系統時間+鎖持有時間” 組合的命令就可以實現。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章