1. 程式人生 > 其它 >Redis的快取穿透、快取擊穿、快取雪崩、熱點資料失效問題及解決方案(轉)

Redis的快取穿透、快取擊穿、快取雪崩、熱點資料失效問題及解決方案(轉)

轉:https://zhuanlan.zhihu.com/p/152223694

​ 在我們的平常的專案中多多少少都會使用到快取,因為一些資料我們沒有必要每次查詢的時候都去查詢到資料庫。特別是高 QPS 的系統,每次都去查詢資料庫,對於你的資料庫來說將是災難。但快取使用不當,也會引起災難。

快取穿透

什麼是快取穿透

​ 正常情況下,我們去查詢的資料都是存在。但如果請求去查詢一條資料庫根本就不存在的資料,也就是快取和資料庫都查詢不到這條資料,但是請求每次都會打到資料庫上面去。這種查詢不存在資料的現象稱為快取穿透。

快取穿透帶來的問題

​ 如果有黑客對你的系統進行攻擊,拿一個不存在的id 去查詢資料,會產生大量的請求到資料庫中,可能會導致你的資料庫由於壓力太大而宕機。

解決方案

1、快取空值

​ 之所以會穿透,是因為快取中沒有儲存這些空資料的key,從而導致每次查詢都到資料庫去了。因此我們可以為這些key對應的值設定null丟到快取裡面去,後面再出現查詢這個key的請求的時候,就直接返回null。不過要設定過期時間。

2、布隆過濾器

​ 這種方式在大資料場景應用比較多,比如Hbase中使用它去判斷資料是否在磁碟上,還有在爬蟲場景判斷URL是否已經被爬取。

​ 這種方案可以加在第一種方案中,在快取之前再加一層布隆過濾器,在查詢的時候先去布隆過濾器查詢key是否存在,如果不存在就直接返回,存在再走查快取和資料庫。

3、使用者鑑權

​ 這種情況有可能是黑客進行惡意攻擊,因此我們可以在系統中增加使用者鑑權校驗或者在介面層增加校驗,直接攔截不正常的請求。

方案選擇

​ 對於一些惡意攻擊,攻擊帶過來的大量的key是不存在的,那麼我們採用第一種方案就會快取大量不存在key的資料,此時第一種方案就不合適了,我們可以先使用第二種方案過濾掉這些key。即針對這種key異常多、請求重複率比較低的資料,我們沒有必要進行快取,使用第二種方案直接過濾掉。

快取擊穿

什麼是快取擊穿

​ 在平常高併發的系統中,大量的請求同時查詢一個key時,此時這個key剛好失效了,就會導致大量的請求打到資料庫上面去,這種現象我們成為快取擊穿。

快取擊穿帶來的問題

​ 會造成某一時刻資料庫請求裡過大,壓力劇增。

解決方案

1、設定熱點資料永不過期

2、加互斥鎖

​ 多個執行緒同時去查詢資料庫的這條資料時,我們可以在第一個查詢資料的請求上使用一個互斥鎖來鎖住它,其他執行緒走到這一步拿不到鎖就等著,等第一個執行緒查詢到了資料,然後做快取。後面的執行緒進來了,就可以直接走快取了。

快取雪崩

什麼是快取雪崩

​ 快取雪崩的情況是,在某一時刻發生大規模的快取失效的情況,比如你的快取服務宕機了,會有大量的請求進來直接打到DB上。結果就是DB撐不住宕機了。

解決方案

1、事前,使用叢集快取,保證快取服務的高可用

​ 這種方案是在發生雪崩前對快取叢集實現高可用,如果是使用Redis,可以使用主從+哨兵或者Redis Cluster來避免Redis全盤崩潰的情況。

2、事中:ehcache本地快取 + Hystrix限流&降級,避免資料庫被打死

​ 使用ehcache本地快取的目的也是考慮在Redis Cluster完全不可用的時候,ehcache本地快取可以支撐一陣。

​ 使用Hystrix進行限流&降級,例如一秒來了3000個請求,我們可以設定只能有一秒1000個請求能通過這個元件,那麼其他剩餘的2000請求就會走限流邏輯。然後去呼叫我們自己開發的降級元件,比如設定一些預設值之類的,以此來保護資料庫不會被大量的請求給打死。

3、事後:開啟Redis持久化機制,儘快恢復快取叢集

​ 一旦重啟,就能從磁碟上自動載入資料恢復記憶體中的資料。

解決熱點資料集中失效問題

什麼是熱點資料集中失效

​ 我們在設定快取的時候,一般會給快取設定一個失效時間,過了這個時間,快取就失效。對於一些熱點的資料來說,當快取失效以後會存在大量的請求過來,然後打到資料庫中去,從而可能導致資料庫崩潰的情況。

解決方案

1、設定不同的過期時間

​ 為了避免這些熱點資料集中失效,那麼我們在設定快取過期時間的時候,儘量讓他們失效的時間錯開。例如在一個基礎的時間上加上或減去一個範圍內的隨機值。

2、互斥鎖

​ 結合上面擊穿的情況,在第一個請求去查詢資料庫的時候加一個互斥鎖,其餘的查詢都會被阻塞住,知道鎖釋放,從而保護資料庫。

​ 但是因為它會阻塞其他執行緒,此時系統吞吐量會下降,需要結合實際的業務去考慮是否要這麼做。