動態

詳情 返回 返回

redis高頻面試題 - 動態 詳情

緩存穿透

概念

緩存穿透是指查詢一個數據庫中不存在的數據,由於這個數據在緩存不存在,所以會直接跳過緩存,直接請求數據庫。

解決辦法

1. 緩存一個空對象

如果查詢的是一個不存在的數據時,可以設置一個短期過期時間的key的數據,然後將它存入緩存中。

2. 布隆過濾器

2.1

先把緩存中的數據的key值存入到布隆過濾器中

2.2

在查詢緩存前,先判斷當前的key值是否存在於布隆過濾器中,其中分為兩個結果

一定不存在 直接返回
有可能存在 再查詢緩存,沒有,在查詢數據庫 

實現原理

image.png

核心組成部分

一個很大的位數組
一組無偏哈希函數

步驟

1.當我們將數據存入reids中,會同時存儲一個Redis的鍵到布隆過濾器中。
它會通過布隆過濾器彙總提供的多個Hash函數對key再進行運算,在對其位數組長度進行取餘得到一個下標,並將該下標值設為1
2.在查詢時,會先按存儲Redis到布隆過濾器的辦法,去判斷當前key值是否存在於布隆過濾器中,結果分為兩種
一定不存在【位數組對應的下標上有一個或多個是0,則直接返回】
有可能存在【位數組對應的下標上每個值都是1】,然後放行,會去查redis

緩存擊穿

概念

Redis中某一個熱點數據的key突然過期,這會導致大量的請求直接訪問數據庫

解決辦法

1,熱點數據永不過期

設置定時任務,在凌晨2點~4點之間訪問量最小的時候更新緩存數據【會刪除緩存中的數據,然後查詢數據庫獲取數據,然後再寫入緩存中】

2.將接口進行降級或限流

短時間內將訪問請求進行限制,直到從數據庫中獲取數據,再寫入緩存中為止

3.進行分佈式鎖

由於在分佈式環境下,傳統鎖會失效,因為傳統鎖是基於JVM的
但是分佈式鎖可以解決這個辦法,下面是具體方案

  1. Zookeeper(基於臨時序號節點 + 監聽機制)
  2. Redisson(基於Redis + Lua腳本)

緩存雪崩問題

概念

Redis緩存中在同一個時間點有大量的key同時過期,用户請求查詢緩存但是緩存中沒有,會直接訪問數據庫

解決方案

1.分佈式鎖
2.熱點數據永不過期
3.設置key隨機過期時間(這個最好)

緩存與數據庫數據一致性?

數據一致性分為強一致性和弱一致性

強一致性

分佈式鎖
把更新數據庫,在刪除緩存的操作當成一個原子性操作,再給這個操作加鎖。但是性能會較差,互聯網中一般不使用
image.png

弱一致性(最終一致性)

1.先更新數據庫,在刪除緩存,這樣雖然用户訪問的時間會短暫出現不一致的情況,但是最終都會一致性
2.基於MySQL的binlog日誌進行異步更新緩存操作,具體使用的技術有

Canal實現實時監聽binlog日誌
使用MQ來異步更新數據

如何保證Redis的高可用性?

原因(單點故障)

Redis以單點模式運行時,如果該節點宕機時,會導致整個依賴Redis的服務不可用。

解決辦法

1. 主從複製

主從架構
在服務器中部署多台Redis實例,並且形成一主多從的形式。主節點負責寫入數據,從節點負責讀取數據。
數據同步
全量複製: 當從節點初次連接主節點時或複製偏移量(offset) 丟失時(如重啓)。主節點會發送一次完整的數據快照(RDB)給從節點,清空舊節點數據並加載數據快照
增量複製: 從節點短線重連後,且其Offset仍在主節點的複製積壓緩衝區範圍內。
然後主節點會通過複製偏移量(offset) 來定位缺失數據並進行同步。
若Offset不在緩衝區(如斷連過久),則會退化為全量複製。
缺點
無自動故障轉移:主節點故障需要手動切換從節點為新主節點。
寫操作單點風險:所有寫請求仍然依賴主節點。

2. 哨兵模式(Sentinel)

哨兵模式是配合主從機制來使用的,其目的是為了提高主從架構的可用性和監控主從架構還是否可用。
前提: 至少3個哨兵節點(避免自身單點故障)
選舉
哨兵實時監控主從架構的節點是否宕機,當主節點宕機後,通知其他哨兵,確認主節點宕機了,通知從節點進行選舉。
主節點選舉:誰的數據多,誰成主節點;誰的數據新,誰成主節點。
缺點
雖然解決了主從節點自動故障轉移,但是寫操作依舊是單節點。

3. Redis集羣(Cluster)(分佈式高可用)

為了解決主節點單點故障問題,可部署Redis集羣。
架構: 多主多從:數據分片到N個主節點,每個主節點配1-N個副本
主從:主節點負責讀寫,從節點只負責同步數據和作為主節點的備選方案。
連接集羣: 只需要連接集羣中的任意一台即可。
如何存儲數據:
會根據key進行hash運算,並對節點的總槽位數取模,得到對應的槽位,把數據放進去。
如果當前連接的不是當前節點,集羣會重定向到要操作的節點上。
如何把同類數據存儲到一個節點上?
1.使用統一前綴:{node}:1,{node}:2
2.使用{} ,Redis會根據{}中的內容自己計算Key的Hash值。

user avatar mannayang 頭像 u_16297326 頭像 sofastack 頭像 u_13529088 頭像 AmbitionGarden 頭像 lenglingx 頭像 zzger 頭像 chuanghongdengdeqingwa_eoxet2 頭像 lvlaotou 頭像 jkdataapi 頭像 nianqingyouweidenangua 頭像 coderdd 頭像
點贊 28 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.