Redis 三大緩存
過去的有些事情不一定要忘記,但一定要放下。
背景:Redis 三大緩存:緩存穿透、緩存擊穿、緩存雪崩,是Redis 面試必須要掌握的東西。
一、緩存穿透
1.概念簡述
緩存穿透是指當用戶在查詢一條數據時,而此時數據庫和緩存卻沒有關於這條數據的任何記錄;而該數據若在緩存中沒找到則會向數據庫請求獲取數據,Redis 拿不到數據時,就會一直查詢數據庫,這樣會對數據庫的訪問造成很大的壓力。
2.案例
用戶查詢一個 id = -1 的商品信息,但是數據庫 id 自增是從 1 開始的,很明顯這條信息是不在數據庫中,當沒有信息返回時,Redis 會一直向數據庫查詢,給當前數據庫訪問造成很大的壓力。
3.解決方案
A、從緩存出發,給緩存設置一個 如果當前數據庫不存在 的信息,把它緩存為一個空對象,返回給用戶;
B、緩存空對象的解決方案代碼簡單,但效果不是很好;可以考慮使用Redis 提供的布隆過濾器。
Redis 布隆過濾器代碼:

1 package com.ausclouds.bdbsec.tjt; 2
3 import com.google.common.hash.BloomFilter; 4 import com.google.common.hash.Funnels; 5
6 import java.nio.charset.Charset; 7
8 /**
9 * Redis 布隆過濾器 10 * 引入依賴: 11 * <dependency> 12 * <groupId>com.google.guava</groupId> 13 * <artifactId>guava</artifactId> 14 * <version>22.0</version> 15 * </dependency> 16 */
17 public class BloomFilterDemon { 18
19 // initial_size: 表示預計放入的元素數量,當實際數量超出這個數值時,誤判率會上升
20 private static long initial_size = 1000000; 21
22 // error_rate: 錯誤率
23 private static double error_rate = 0.0001; 24
25 public static void main(String[] args) { 26 BloomFilter<String> bloomFilter =
27 BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), initial_size, error_rate); 28 bloomFilter.put("what"); 29 boolean isContain = bloomFilter.mightContain("what"); 30
31 } 32
33
34 }
緩存空對象流程圖
二、緩存擊穿
1.概念簡述
緩存擊穿是指有某個key 經常被查詢,或者某個key 不經常被訪問,而這個時候,若該key 在緩存的過期時間失效或者是個冷門key 的時候,突然有大量關於這個key 的訪問請求,這樣就會導致大並發請求直接穿透緩存,請求數據庫,瞬間增大了數據庫的訪問壓力。
2.案例
(1)一個“冷門”key,突然被大量用戶請求訪問;
(2)一個“熱門”key,在緩存中時間恰好過期,這時有大量用戶來進行訪問。
緩存擊穿案例圖
3.解決方案
對於緩存擊穿問題,常用的解決方案是加鎖;對於key 過期問題,當key 要查詢數據庫的時候加上鎖,保證只能讓第一個請求進行查詢數據庫操作,然后把從數據庫中查詢到的值存儲到緩存中,對於剩下的相同的key,則可直接從緩存中獲取。
緩存擊穿解決方案圖
三、緩存雪崩
1.概念簡述
緩存雪崩是指在某一個時間段內,緩存集中過期失效,若這個時間段內有大量請求,並且查詢數據量巨大,所有的請求都會查詢數據庫,使數據庫的調用瞬間量劇增,引起數據庫壓力過大甚至宕機。(Redis 突然宕機或大部分數據失效)
2.案例
某寶雙十一購物節,在 23:00-24:00 舉行商品促銷活動。開發人員是這么設計的:在 23:00 把商家促銷的商品放到緩存中,並通過redis 的expire 設置了過期時間為1小時;這個時間段許多用戶在訪問這些商品信息,但是剛好到了24:00點的時候,恰好還有許多用戶在訪問這些商品,此時對這些商品的訪問都會轉到數據庫上,導致數據庫壓力突然劇增,甚至直接宕機。
3.解決方案
A、限流降級
在緩存失效后,通過加鎖或者隊列來控制讀數據庫寫緩存和寫緩存的線程數量,對某個key 同一時刻只允許一個線程執行查詢設計和寫緩存操作。
B、Redis 高可用
可能會出現Redis 掛掉的情況,多增加幾台Redis 實例(一主多從),即使一台掛掉之后其他的還可以繼續工作。
C、不同過期時間
設置不同的過期時間,讓緩存失效的時間盡量均勻,避免同一時間大量緩存失效。
D、數據預加熱
數據加熱的含義就是在正式部署之前,先把可能用到的數據預先訪問一遍,這樣部分可能大量訪問的數據就會加載到緩存中;一般可以在即將發生大並發訪問前手動觸發加載緩存不同的key。
過去的有些事情不一定要忘記
但一定要放下