目錄
- 1、緩存雪崩
- 2、緩存穿透
- 3、緩存預熱
- 4、redis 為什麼這麼快
- 參考連結
1、緩存雪崩
問題描述:在原緩存資料失效,而新緩存資料未到位期間(例如:當設定緩存時采用了相同的過期時間,在同一時刻出現大面積的緩存過期),此時所有原本應該通路緩存的請求都去查詢資料庫了,進而對資料庫 CPU 和記憶體造成巨大壓力。
解決方法:
- 方法一,對通路資料庫的代碼塊使用加鎖或隊列的方式避免大量線程同時通路資料庫,這種方法會造成大量線程排隊阻塞,并不會提高系統吞吐量,在高并發場景中很少使用。
- 方法二,利用随機值等方式為不同的 key 設定不同的失效時間,盡量使失效時間均勻分布。
- 方法三,二級緩存,設定 A1 為主緩存,A2 為副緩存,A1 的失效時間設定為短期,A2 為長期,當 A1 失效時,線程可以先去通路 A2。
- 方法四,為每一個緩存資料都對應一個标志(該标志實質上也是緩存系統中一個資料),設定标志的過期時間小于對應資料的過期時間。這樣,當查詢該資料時,若發現标志已過期,則提前去更新該資料(可先将老資料給使用者)。
2、緩存穿透
問題描述:線程查詢某個資料時,資料庫并不存在該資料,自然緩存中也不會有該資料,導緻線程每次查詢時,在緩存中找不到,都會再去資料庫中查一次。
解決方法:
- 方法一,布隆過濾器,将所有存在的資料哈希到一個足夠大的bitmap中,查詢不存在的資料會被bitmap攔截,進而避免對底層存儲系統的壓力。
- 方法二,若一次查詢的傳回為空,仍然将這個“空值”進行緩存(但一般設定很短的過期時間),這樣下次再查詢就可以從緩存中讀到空值,不會再繼續通路資料庫。
3、緩存預熱
系統上線後,可以選擇将緩存資料直接加載到緩存系統中,避免使用者第一次請求時總是先查詢資料庫,再緩存資料。
4、redis 為什麼這麼快
- 基于記憶體,絕大部分請求是純粹基于記憶體的操作,速度快;
- 資料結構簡單,是以對資料的操作也簡單快速;
- 網絡請求子產品采用單線程模式,避免了不必要的上下文切換和競争條件;
- 使用多路 I/O 複用模型,非阻塞 IO。
需要注意的是,redis 的單線程隻是說網絡請求子產品的單線程的。同時 redis 使用了多路 I/O 複用模型,多路 I/O 複用模型是利用 select、poll、epoll 可以同時監察多個流的 I/O 事件的能力,在空閑的時候,會把目前線程阻塞掉,當有一個或多個流有 I/O 事件時,就從阻塞态中喚醒,于是程式就會輪詢一遍所有的流(epoll 是隻輪詢那些真正發出了事件的流)。這裡“多路”指的是多個網絡連接配接,“複用”指的是複用同一個線程。采用多路 I/O 複用技術可以讓單個線程高效的處理多個連接配接請求(盡量減少網絡 IO 的時間消耗),且 redis 在記憶體中操作資料的速度非常快,也就是說記憶體内的操作不會成為影響 redis 性能的瓶頸,主要由以上幾點造就了 redis 具有很高的吞吐量。

參考連結
https://www.toutiao.com/a6533812974807679495