Redis 面試常見問題
Redis常見問題
-
為什麼使用Redis
效能和併發(分散式鎖還有其他中介軟體可以代替)
-
效能
需要執行耗時特別久,且結果不頻繁變動的結果,將執行結果放入快取。後面的請求去快取中獲取,使得請求能夠迅速響應。
-
併發
在大併發情況下,所有的請求直接訪問資料庫,資料庫會出現連線異常。
使用Redis做一個緩衝操作,讓請求先訪問Redis,而不是直接訪問資料庫
-
-
使用Redis有什麼缺點
- 快取和資料庫雙寫一致性問題
- 快取雪崩問題
- 快取擊穿問題
- 快取的併發競爭問題
-
單執行緒的Redis問什麼這麼快
- 純記憶體操作
- 單執行緒操作,避免了頻繁的上下文切換
- 採用了非阻塞 I/O 多路複用機制(單個執行緒,通過跟蹤每個 I/O 流的狀態,來管理多個 I/O 流)
-
Redis的資料型別,以及每種資料型別的使用場景
-
String
最常規的 set/get 操作,一般做一些複雜的計數功能的快取
-
Hash
value 存放的是結構化的物件,比較方便操作其中的某個欄位。
-
List
可以做簡單的訊息佇列的功能。
可以利用 lrange 命令,做基於Redis的分頁功能
-
Set
可以做全域性去重的功能(如果使用 JVM 自帶的Set進行去重,還需要起一個公共服務)
利用交集、並集、差集操作,計算共同喜好、全部喜好、獨有喜好
-
Sorted Set
多了一個權重引數 Score, 集合中的元素能夠按 Score 進行排列
可以做排行榜應用。延時任務。範圍查詢
-
-
Redis 的過期策略以及記憶體淘汰機制
Redis 採用定期刪除 + 惰性刪除策略
-
為什麼不用定時刪除策略
定時刪除,需要用一個定時器來負責監視 Key,過期自動刪除。十分消耗 CPU 資源。
在大併發請求下,CPU 要將時間應用在處理請求,而不是刪除 Key。
-
定期刪除 + 惰性刪除如何工作
定期刪除,Redis 預設每 100ms 檢查,是否有過期的 Key,有過期的 Key 則刪除。
檢查並不是將所有的 Key 都進行檢查,而是隨機抽取檢查。
只採用定期刪除策略,會導致很多 Key 到時間沒有刪除。於是,就引入了惰性刪除。
惰性刪除,在獲取某個 Key 的時候,Redis 會檢查一下,這個 Key 如果設定了過期時間,那麼是否過期了?如果過期了此時就會刪除
採用定期刪除+惰性刪除為什麼記憶體還是越來越高?
如果定期刪除沒刪除 key。然後也沒有即時去請求 Key,也就是說惰性刪除也沒生效。Redis的記憶體會越來越高。那麼就應該採用記憶體淘汰機制。
在 redis.conf 中有一行配置:
# maxmemory-policy volatile-lru
該配置就是配記憶體淘汰策略的:
- noeviction: 當記憶體不足以容納新寫入資料時,新寫入操作會報錯。
- allkeys-lru: 當記憶體不足以容納新寫入資料時,在鍵空間中,移除最近很少使用的 Key。
- allkeys-random: 當記憶體不足以容納新寫入資料時,在鍵空間中,隨機移除某個 Key。
- volatile-lru: 當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,移除最少使用的 Key。
- volatile-random: 當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,隨機移除某個 Key。
- **volatile-ttl:**當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,有更早過期時間的 Key 優先移除。
-
-
Redis 和資料庫雙寫一致性問題
一致性問題是分散式常見問題,還可以再分為最終一致性和強一致性。資料庫和快取雙寫,就必然存在不一致的問題。
採取正確更新策略,先更新資料庫,再刪快取。其次,因為可能存在刪除快取失敗的問題,提供一個補償措施。
-
如何應對快取穿透和快取雪崩問題
**快取穿透,**請求快取中不存在的資料,導致所有的請求都傳至資料庫上,導致資料庫連線異常。
快取穿透解決方案:
- **利用互斥鎖:**快取失效的時候,先獲得鎖,得到鎖了,再去請求資料庫。沒得到鎖,則休眠一段時間重試。
- 採用非同步更新策略,無論 Key 是否取到值,都直接返回。
- 提供一個能迅速判斷請求是否有效的攔截機制
**快取雪崩,**即快取同一時間大面積的失效,同時又來了一波請求,結果請求都傳至資料庫,從而導致資料庫連線異常。
快取雪崩解決方案:
-
給快取的失效時間,加一個隨機值,避免集體失效
-
使用互斥鎖
-
雙快取。有兩個快取,快取 A 和快取 B。快取 A 的失效時間為 20 分鐘,快取 B 不設失效時間。自己做快取預熱操作。
從快取 A 讀資料,有則直接返回;A 沒有資料,直接從 B 讀資料,直接返回,並且非同步啟動一個更新執行緒,更新執行緒同時更新快取 A 和快取 B。
-
如何解決 Redis 的併發競爭 Key 問題
這個問題引發原因是,同時有多個子系統去 Set 一個 Key。
-
如果對這個 Key 操作,不要求順序
準備一個分散式鎖,大家去搶鎖,搶到鎖就做 set 操作
-
如果對這個 Key 操作,要求順序
在資料寫入時,同時儲存一個時間戳。
寫入 Redis 前,比較時間戳,如果早於快取中的時間戳,則不做 set 操作。
也可以利用佇列,set方法變成序列訪問
-