關於【緩存穿透,緩存擊穿,緩存雪崩,熱點數據丟失】問題的解決方案

本篇文章轉載自:石衫的架構筆記 微信公衆號redis

前言

當咱們系統中使用到了緩存時,無論是一級緩存仍是多級緩存,它的做用就是業務系統在請求數據時,若是緩存中有,就從緩存中獲取;若是緩存中沒有,再去訪問DB,從而減小DB的壓力,縮短獲取數據的時間。那麼在使用緩存的過程當中,會出現哪些常見問題?咱們又如何來解決?數據庫

1 緩存穿透

1.1 什麼是緩存穿透

正常狀況下,咱們去查詢數據都是存在的。緩存

那麼請求查詢一條壓根在數據庫中就不存在的數據,即在緩存和數據庫中都沒有這條數據,可是請求每次在緩存中找不到,就去訪問數據庫,比較佔用和消耗數據庫的資源,這種現象,就叫作緩存穿透。服務器

1.2 穿透帶來的問題

黑客攻擊系統,經過緩存穿透,使用一個不存在的id,大量訪問系統的接口,系統由於緩存中沒有數據,而去大量的訪問數據庫,致使數據庫資源被無效佔用,影響甚至拖垮正常業務。微信

1.3 解決辦法

1.3.1 緩存空值

咱們知道,緩存服務器(redis)通常是經過key value來存儲緩存數據的。當有請求過來,會經過key在緩存中查找數據。而發生緩存擊穿的問題,是由於緩存服務器中沒有存儲這些無效數據的key,從而致使無效請求訪問到數據庫。架構

那麼咱們能夠在這些請求訪問數據庫後,沒有獲得查詢結果時,在緩存服務器中存儲這個key,並設置它的值爲null,這樣當再次發生查詢這個key的請求時,緩存服務器就直接返回null,不去訪問數據庫了。併發

可是不要忘記,設置緩存失效時間,方便正確數據的錄入和更新。分佈式

1.3.2 BloomFilter

BloomFilter相似於一個hbase set用來判斷某個元素(key)是否存在於某個集合中。高併發

這種方式在大數據應用場景比較多,好比Hbase(HBase是一個分佈式的、面向列的開源數據庫)中使用它去判斷數據是否在磁盤上。還有在爬蟲場景判斷url是否已經被爬取過。性能

這種方式能夠加在第一種方案中,在緩存以前再加一層BloomFilter去查詢key是否存在,若是不存在直接返回,存在再去查詢緩存或者DB。

1.4 如何選擇

針對大量惡意請求攻擊,若是key重複多,使用第一種方案是有效的。

若是惡意請求key不重複的多,則使用第二種方案最有效。

2 緩存擊穿

2.1 什麼是緩存擊穿

在日常高併發的系統中,大量的請求同事查詢到一個key時,此時這個key正好失效了,就會致使大量的請求都轉到數據庫上面了,這種現象咱們成爲緩存擊穿。

2.2 會帶來什麼問題

會形成數據庫訪問量忽然增大,壓力劇增。

2.3 如何解決

上面的現象是多個線程同時去查詢數據庫的這條數據,那麼我能夠在第一個查詢數據的請求上使用一個 互斥鎖 來鎖住它。

其餘的線程走到這一步拿不到鎖就等待,等到第一個線程查詢到了數據,而後作緩存,後面的線程進來發現已經有緩存了,就能夠直接獲取緩存,而不訪問數據庫了。

3 緩存雪崩

3.1 什麼是緩存雪崩

在當某一時刻發生大規模的緩存失效的狀況,好比你的緩存服務宕機了,會有大量的請求直接請求數據庫上,結果數據庫就撐不住了,也跟着掛掉了。

3.2 解決辦法

3.2.1 事前:

使用集羣緩存,保證緩存服務器的高可用。

好比使用redis,就要考慮到 主 從 + 哨兵和 集羣 來避免redis的全面崩盤的狀況。

3.2.2 事中:

ehcahe本地緩存 + Hystrix限流&降級,避免DB被打死

使用ehcahe本地緩存的目的也是考慮在redis集羣徹底不可用的時候,ehcahe本地緩存還能支撐一陣。

使用Hystrix進行限流&降級,好比一秒來了5000個請求,咱們假設只能有一秒2000個請求經過這個組件,那麼其餘3000個請求就會走限流邏輯。

而後去調用咱們本身開發的降級組件,好比設置一些默認值之類的,以此來保護DB不會被大量請求搞的宕機。

3.2.3 過後:

開啓redis的持久化機制,恢復緩存服務器集羣

緩存服務器重啓,根據配置的持久化策略,會讀取日誌文件,恢復內存中的數據。

4 解決熱點數據集中失效的問題

咱們在設置緩存的時候,通常也會設置緩存的失效時間,過了這個時間,緩存失效了。

若是這批數據,是請求量比較高的,那麼請求就會轉到數據庫去,數據庫壓力瞬間增大,性能降低甚至宕機。

就是緩存擊穿現象。

4.1 解決辦法

4.1.1 設置不一樣的失效時間

避免熱點數據集中失效,在設置緩存時間時,咱們讓它們的失效時間錯開。好比在一個基礎的時間上加上或減去一個範圍內的隨機值。

4.1.2 互斥鎖

結合上面提到的請求,在高併發請求中,在第一個請求去查詢數據庫的時候對它加一個互斥鎖,其他的查詢請求都會被組塞住,直到鎖被釋放,從而保護數據庫。

可是也是由於它會阻塞其餘線程,系統的吞吐量也會降低,須要結合業務中的實際須要來考慮要不要這麼作。

相關文章
相關標籤/搜索