1. 程式人生 > 實用技巧 >Redis 面試複習題

Redis 面試複習題

1.Redis支援的資料型別?

  • String 字串

  • List 列表 相當於Java裡的LinkedList 常用於訊息佇列和非同步邏輯處理

    • lpush 插入值到列表頭部
    • rpush 插入值到列表尾部(這個用於實現佇列右進左出) rpush books java python go
    • blpop 取出列表第一個元素,當沒有元素時會等待N秒,超時返回nil [blpop xxx 10]
    • brpop 取出列表最後一個元素
    • LINSERT 在某個list列表前或後插入元素,當這個列表為空時則不做任何操作 [LINSERT list1 BEFORE "bar" "Yes"
      ]
    • lindex 根據下標獲取列表值 負數代表倒數幾位 [lindex course 1]
    • llen 返回列表長度 [llen course]
    • lrange 返回下標範圍內的元素列 [lrange course 0 2]
  • Set 集合 相當於Java的HashSet 鍵值無序唯一 常用與去重功能

    • sadd 插入值 [sadd user user1]
    • smembers 返回該key所有的集合 [smembers user]
    • sismember 判斷這個值是否存在 [sismember user user1]
    • scard 返回列表長度 [scard user]
  • ZSet 有序列表 有序的HashMap 並且每個值都賦予一個score代表權重排序 常用與關注時間列表排序、名次排名等

    • zadd 插入值 [zadd books 8.9 "21天學會Java"]
    • zrange 按score排序列出,可篩選出範圍 [zrange books 0 -1]
    • zrevrange 按score逆序列出 [zrevrange books 0 -1]
    • zcard 返回列表長度 [zcard books]
    • zscore 獲取指定value的score(因為score是用double儲存,因此會存在小數點精度問題) [zscore books "21天學會Java"]
    • zrank 獲取排名 [zrank books "21天學會Java"
      ]
    • zrangebyscore 返回根據score篩選的列表(這裡的值無窮大可以用inf代替) [zrangebyscore books 0 8.91] | [zrangebyscore books -inf 8.91 withscores]
    • zrem 刪除該value [zrem books "21天學會Java"]
  • Hash 欄位 相當於Java裡的HashMap 實現為陣列+連結串列 常用於儲存屬性

    • hset 插入一條資料 [hset user1 age 29]
    • hincrby 計數 [hincrby user1 age 1]

2.什麼是Redis持久化?Redis有哪幾種持久化方式?優缺點是什麼?

Redis持久化是為了避免程序崩潰導致資料丟失問題

主要有RDB和AOF兩種持久化方式


RDB

RDB會每隔一段時間把記憶體資料以二進位制檔案形式寫入磁碟。檔名為dump.rdb

RDB有三種機制:save、bgsave、自動化

save命令會阻塞redis伺服器,直到RDB完成為止。

bgsave命令會建立一個子程序非同步進行RDB,建立過程會阻塞。

自動化是在redis.conf配置好規則進行自動觸發。

優點是全量備份,這樣在恢復資料時速度會比AOP快。

缺點是在全量備份時,父程序在被修改資料時,子程序在做備份時有可能會忽略了資料,因此在持久化期間修改的資料無法儲存下來,可能會丟失資料


AOF

AOF會把所有接收到的命令以命令文字方式一行一行的追加到備份檔案中,其實就是日誌記錄。

AOF有三種機制:always、everysec、no

always只要有資料變更就會立刻記錄到磁碟中,因此效能較差但資料完整性很好

everysec是非同步操作,並不會馬上記錄到磁碟而是每秒一個非同步程序來做記錄磁碟操作,因此如果在非同步步驟宕機,那就會丟失資料。

on是從不同不

優點是能夠準時的錄入磁碟防止丟失資料
缺點是恢復資料時比RDB慢,因為AOF是儲存命令機制,因此恢復時會講所有的命令從頭開始執行一遍,還有就是在效能消耗上,AOF每秒都要執行一次記錄,因此會消耗少許的效能。

3.Redis 有哪些架構模式?講講各自的特點

Redis主要有單機模式(主從複製)、哨兵、叢集(proxy、直連)

單機模式:容量有限、不能保證高可用
主從複製:主要從master複製資料到從庫中,從而降低master的讀取壓力
哨兵:結構依然是主從模式,新增sentinel的分散式監控系統,當監控到master有異常時,會進行自動遷移選舉master。這樣保證了高可用,缺點是依然是主從模式,沒有辦法解決master寫入的壓力。
叢集直連:redis3.0後新增redis-cluster的叢集概念,主要是採用無中心結構,每個節點互相同步

4.使用過Redis分散式鎖麼,它是怎麼實現的?

首先Redis的操作是可以保證原子性的,因為Redis是單執行緒的關係。

其次,光一個操作具有原子性是不夠的,當我們使用setnx執行新增快取,再新增expire,這樣拆分開兩個指令的話,假設在setnx成功後伺服器掛了,這樣沒有過期時間就會造成死鎖。因此使用整合成一套指令的 jedis.set(String key, String value, String nxxx, String expx, int time) 這個實現方法是最佳選擇,當然傳LUA指令碼來實現也是可以的。

5.使用過Redis做非同步佇列麼,你是怎麼用的?有什麼缺點?

6.什麼是快取穿透?如何避免?什麼是快取雪崩?如何避免?

快取穿透就是當用戶去查詢資料時,發現快取沒有命中,而接著去資料庫查也沒找到資料,這樣會給資料庫帶來很大的壓力。

這種情況有可能是受到攻擊,把一些不存在的值大量傳過來,因此解決方案為

  1. 加強基礎值校驗
  2. 快取空物件,設定一個較短的時間,以保證不被反覆攻擊

快取擊穿是指快取沒有但資料庫中有資料,導致資料庫壓力過大

  1. 熱點資料先快取或永不過期

快取雪崩就是大批資料同時過期,使得查詢資料量過大,引起資料庫壓力過大導致崩潰

與快取擊穿不同在於 快取擊穿是針對同一個資料,而快取雪崩是不同資料同一時間過期

  1. 資料庫過期時間隨機過期
  2. 限流降級

7.為什麼Redis 單執行緒卻能支撐高併發?

  1. redis是基於記憶體的,記憶體的速寫速度非常快
  2. redis是基於非阻塞IO多路複用機制
  3. redis單執行緒,省去切換執行緒的時間

8.說說Redis的記憶體淘汰策略

  1. 定時掃描策略
  • Redis預設每秒進行10次過期掃描,每次從過期字典中隨機選出20個key
  • 刪除這20個key中已過期的key
  • 如果過期的key的比例超過1/4,則繼續重複第一步。
  1. 惰性次略
  • 當客戶端訪問key時,Redis會對key進行過期時間檢查,如果過期就立即刪除。

9.說說從節點的過期策略

從節點是不會進行掃描的,主節點的key到期時會從AOF檔案新增一條del的指令,然後同步到從節點,從節點通過執行這條指令來實現刪除過期的key。

10.Redis的併發競爭問題如何解決?

  1. redis分散式鎖
  2. 客戶端加鎖(synchronized)

11.Redis中List和ZSet的儲存結構是怎麼實現的

List

List內部每個元素是使用ziplist的儲存結構來實現的,即壓縮列表,當資料少時他會分配一塊連續的記憶體給他用於儲存,當資料多了之後會改為quicklist的儲存方式

ziplist是一種特殊的雙向連結串列,他內部並沒有雙向指標,而是儲存上一個元素的長度和當前元素的長度,通過長度推算下一個元素。

quickList其實就是把linkedlist和ziplist結合到一起,當使用quickList時,就不會繼續使用ziplist的邏輯,quickList會為每個ziplist建立一個quicklistNode,然後在quicklistNode裡包含ziplist,quicklistNode來實現prev和next指標。


ZSet

是使用資料結構跳躍列表實現的,這塊暫時還不熟悉,後續會單獨寫一篇來詳細介紹