天天看點

redis 緩存穿透等問題解決方案

在使用redis中可能會發生以下情況:

緩存出現的問題

緩存穿透

通路redis一個(或多個)不存在的資料,擊穿redis到達DB。查詢DB仍傳回空。大量這樣的通路可能會使DB崩潰。

緩存雪崩

緩存系統同一時間有大量資料失效。大量資料打到DB使DB壓力過大。

緩存并發

和上面類似,不過這個是當一個key過期時大量請求打到DB。

解決方法

以上三種情況差別在于緩存穿透是惡意的,即通過大量構造不存在的key攻擊系統。而後兩個緩存雪崩和緩存并發則是緩存失效時出現的問題。緩存雪崩是大量key失效,緩存并發是某個(或某些)緩存失效。

先看緩存穿透,是惡意構造大量不存在的key攻擊系統。解決方法:

  1. 在redis層之前做一層過濾,判斷查詢的key是否符合規則(或者布隆過濾,或者依據key的生成規則進行過濾)。若不符合直接傳回,可攔截惡意請求。
  2. 若判斷不出key的真假,查詢到達DB後沒有資料,則将空值也寫入redis。下次查詢就直接打到緩存了(緩存設定較短的過期時間)。

下面是緩存雪崩和緩存并發。

緩存雪崩在于同時大量緩存失效,可在設定緩存時為資料設定不同的過期時間,可大大避免緩存同時失效。

緩存并發在于某些緩存失效了,這個無法避免,緩存隻要有過期時間就有失效的那一刻。當大量請求過來時,這裡可以使用分布式鎖限制對于同一個key的查詢,某個時刻隻有一個線程可以查詢DB。具體:

請求到達redis擊穿後(redis沒有查詢到),根據請求key通路分布式鎖,擷取鎖的線程才可以通路DB并更新緩存。這樣就可以限制每個通路同一個key的多個線程隻有一個才能通路DB并更新緩存。(分布式鎖設定過期時間,避免被鎖死,沒有擷取鎖的線程可以休眠一段時間後重試擷取緩存)

總結過來就是:

  1. 在redis層之前做一層過濾,判斷查詢的key是否符合規則(或者布隆過濾,或者依據key的生成規則進行過濾)。若不符合直接傳回,可攔截惡意請求。
  2. 請求在redis中沒有到,則根據請求key通路分布式鎖,擷取鎖的線程才可以通路DB并更新緩存(更新緩存時若在DB中沒有查到,也更新緩存,隻是更新一個特殊空值,設定過期時間)。這樣就可以限制每個通路同一個key的多個線程隻有一個才能通路DB并更新緩存。(分布式鎖設定過期時間,避免被鎖死,沒有擷取鎖的線程可以休眠一段時間後重試擷取緩存)
  3. 将可能成為熱點的key的過期時間設定不一樣,防止緩存雪崩。

繼續閱讀