Redis緩存穿透,雪崩,擊穿現象與解決辦法


Redis緩存穿透,雪崩,擊穿現象與解決辦法

一.緩存穿透

1.什么是緩存穿透

緩存穿透,是指查詢一個數據庫一定不存在的數據。

例如:對於系統A,假設一秒 5000 個請求,結果其中 4000 個請求是黑客發出的惡意攻擊。黑客發出的那 4000 個攻擊,緩存中查不到,每次你去數據庫里查,也查不到。這種惡意攻擊場景的緩存穿透就會直接把數據庫給打死

2.解決辦法

(1)采用布隆過濾器BloomFilter

將所有可能存在的數據哈 希到一個足夠大的 bitmap 中,一個一定不存在的數據會被這個 bitmap 攔截掉,從而避免了對底層存儲系統的查詢壓力

(2)緩存空值

如果一個查詢返回的數據為空(不管是數據不 存在,還是系統故障)我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鍾。 通過這個直接設置的默認值存放到緩存,這樣第二次到緩沖中獲取就有值了,而不會繼續訪問數據庫

(3)接口限流與熔斷、降級

重要的接口一定要做好限流策略,防止用戶惡意刷接口,同時要降級准備,當接口中的某些服務不可用時候,進行熔斷,失敗快速返回機制。

-------------------------------------------- 黃金切割線 --------------------------------------------

二.緩存雪崩

1.什么是緩存雪崩

緩存雪崩,是指在某一個時間段,緩存集中過期失效。

舉個栗子:如果首頁所有 Key 的失效時間都是 12 小時,中午 12 點刷新的,我零點有個大促活動大量用戶涌入,假設每秒 6000 個請求,本來緩存可以抗住每秒 5000 個請求,但是緩存中所有 Key 都失效了。此時 6000 個/秒的請求全部落在了數據庫上,數據庫必然扛不住,真實情況可能 DBA 都沒反應過來直接掛了。

2.解決辦法

(1)加鎖排隊

key: whiltList value:1000w個uid 指定setNx whiltList value nullValue mutex互斥鎖解決,Redis的SETNX去set一個mutex key, 當操作返回成功時,再進行load db的操作並回設緩存; 否則,就重試整個get緩存的方法

(2) 數據預熱

緩存預熱就是系統上線后,將相關的緩存數據直接加載到緩存系統。這樣就可以避免在用戶請求的時候,先查詢數據庫,然后再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據!可以通過緩存reload機制,預先去更新緩存,再即將發生大並發訪問前手動觸發加載緩存不同的key

(3) 雙層緩存策略

C1為原始緩存,C2為拷貝緩存,C1失效時,可以訪問C2,C1緩存失效時間設置為短期,C2設置為長期。

(4) 定時更新緩存策略

失效性要求不高的緩存,容器啟動初始化加載,采用定時任務更新或移除緩存,

(5)不同過期時間

設置不同的過期時間,讓緩存失效的時間點盡量均勻

(6)熱點數據永不過期

部分用戶訪問特別頻繁的熱點數據,設置永不過期

-------------------------------------------- 黃金切割線 --------------------------------------------

三.緩存擊穿

1.什么是緩存擊穿

緩存擊穿是指一個 Key 非常熱點,在不停地扛着大量的請求,大並發集中對這一個點進行訪問,當這個 Key 在失效的瞬間,持續的大並發直接落到了數據庫上,就在這個 Key 的點上擊穿了緩存。

2.解決辦法

(1)互斥鎖

public static String getData(String key) throws InterruptedException {
        //從Redis查詢數據
        String result = getDataByKV(key);
        //參數校驗
        if (StringUtils.isBlank(result)) {
            try {
                //獲得鎖
                if (reenLock.tryLock()) {
                    //去數據庫查詢
                    result = getDataByDB(key);
                    //校驗
                    if (StringUtils.isNotBlank(result)) {
                        //插進緩存
                        setDataToKV(key, result);
                    }
                } else {
                    //睡一會再拿
                    Thread.sleep(100L);
                    result = getData(key);
                }
            } finally {
                //釋放鎖
                reenLock.unlock();
            }
        }
        return result;
    }

(2)熱點數據永不過期

不過期將不存在該問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM