redis - 快取雪崩、擊穿、穿透

Po-Ching Liu
Jul 15, 2021

--

提到in-memory cache就會提到redis,redis的特性諸如 single thread、快速、支援多種語言、cluster、哨兵模式等,本篇文章皆不會概述xD。本篇文章主要想記錄在維護高併發、高流量(電商、券商等)的系統時,在使用in-memory cache不管是VM自己的lcoal cache又或者是redis,可能會遇到的問題以及其解法,其中包含

1. 快取雪崩 (Cache Avalanche, 緩存雪崩)
2. 快取擊穿 (Hotspot Invalid, 緩存擊穿)
3. 快取穿透 (Cache Penetration, 緩存穿透)

話不多說,就開始吧!!~

快取雪崩 (Cache Avalanche, 緩存雪崩)

" 什麼是快取雪崩 ? "
在某個時刻所有的 cache同時發生過期或者redis 服務失效,導致大量的 request 直接打在資料庫上,當流量巨大時資料庫很可能會被打掛,此時DBA若重啟資料庫可能又會被新的一波流量再打掛,這樣的狀況就是快取雪崩。

解決方案 -
因為是同個時間點,所有的cache key大規模失效,因此可以在設定 cache 時,給予每個cache key 隨機的過期時間,或者 不設定過期時間 。每個cache key 過期時間的設定,其核心理念在你想要更新資料的頻率。

快取擊穿 (Hotspot Invalid, 緩存擊穿)

" 什麼是快取擊穿 ? “
快取擊穿和快取雪崩相似,雪崩是大面積cache key時間過期,而快取擊穿則是某個熱門的 cache key過期。所以,當高併發集中在此熱門的key又快取失效過期時,流量就會直接打在資料庫上,這樣子的狀況就叫快取擊穿。

解決方案 -
要避免快取擊穿其中一個方法是將熱點key設為不過期,另一個方法則是在application寫lock(互斥鎖)以確保共用資源在多執行緒下可以排隊拿取資源,不過此作法會造成系統吞吐量下降,並阻礙其他線程。

快取穿透 (Cache Penetration, 緩存穿透)

" 什麼是快取穿透 ? “
快取穿透是指client request 的資料並不存在於 cache 中並且也不存在於資料庫中,因此每次的請求就會直接穿過cache並打在資料庫中。同樣,若這樣類行的請求量一多,也是會將資料庫打掛。
舉個簡單的例子,若 client 請求 id=-1的資料,但是在我們的資料庫中是從id =1開始的流水號,那麼-1則永遠不會拿到資料,並且請求會直接打在資料庫上。

解決方案 -
因為是查找不存在的資料,因此可以在application中過濾非法請求,也就是當client 請求id = -1時,直接將請求做例外處理,不要讓他打在資料庫上。另一種方式,則是將id=-1寫入cache中並回傳對應的處理,例如當id=-1則redis則回傳null。還有另一種方式則是使用 " 布隆過濾器 "(Bloom Filter)判斷請求的key是否存在於集合中,若存在則直接去redis拿取,若不在則直接回傳對應訊息。

以上是高併發、高流量系統在使用cache上會遇到的問題,這些也是面試時時常會問的問題,筆者以此做為紀錄並分享。

--

--