天天看點

第7章 分布式系統架構 【補充:緩存穿透、緩存擊穿與失效時的雪崩效應】

12、緩存穿透、緩存擊穿與失效時的雪崩效應(補充)

參考自網絡,具體出版忘記了

12.1 緩存穿透

描述:

緩存穿透是指緩存和資料庫中都沒有的資料,而使用者不斷發起請求。由于緩存是不命中時被動寫的,并且出于容錯考慮,如果從存儲層查不到資料則不寫入緩存,這将導緻這個不存在的資料每次請求都要到存儲層去查詢,失去了緩存的意義。

在流量大時,可能DB就挂掉了,要是有人利用不存在的key頻繁攻擊我們的應用,這就是漏洞。

如發起為id為“-1”的資料或id為特别大不存在的資料。這時的使用者很可能是攻擊者,攻擊會導緻資料庫壓力過大。

解決方案:

接口層增加校驗,如使用者鑒權校驗,id做基礎校驗,id<=0的直接攔截;

從緩存取不到的資料,在資料庫中也沒有取到,這時也可以将key-value對寫為key-null,緩存有效時間可以設定短點,如30秒(設定太長會導緻正常情況也沒法使用)。這樣可以防止攻擊使用者反複用同一個id暴力攻擊

12.2 緩存擊穿

描述:

緩存擊穿是指緩存中沒有但資料庫中有的資料(一般是緩存時間到期),這時由于并發使用者特别多,同時讀緩存沒讀到資料,又同時去資料庫去取資料,引起資料庫壓力瞬間增大,造成過大壓力。

解決方案:

1)設定熱點資料永遠不過期。

2)接口限流與熔斷,降級。重要的接口一定要做好限流政策,防止使用者惡意刷接口,同時要降級準備,當接口中的某些 服務  不可用時候,進行熔斷,失敗快速傳回機制。

3)布隆過濾器。bloomfilter就類似于一個hash set,用于快速判某個元素是否存在于集合中,其典型的應用場景就是快速判斷一個key是否存在于某容器,不存在就直接傳回。布隆過濾器的關鍵就在于hash算法和容器大小,

4)加互斥鎖,互斥鎖參考代碼如下:

public static String getData(String key) throws InterruptedException\
{
    //從緩存讀取資料
    String result = getDataFromRedis(key); 
    //緩存中不存在資料.
    if (result == null)
    {
        //去擷取鎖,擷取成功,去資料庫取資料
        if (reenLock. tryLock())
        {
            //從資料擷取資料	
            result = getDataFromMysql(key);
            //更新緩存資料
            if (result != null)
            {
                setDataToCache(key , result);
            }
            //釋放鎖
            reenLock .unlock();
        }
    }
    else
    {    //擷取鎖失敗
        //暫停100ms再重新去擷取資料
        Thread. sleep(100);
        result = getData(key);
    }
    return result;
}
           

說明:

1)緩存中有資料,直接走String result = getDataFromRedis(key); 後就傳回結果了

2)緩存中沒有資料,第1個進入的線程,擷取鎖并從資料庫去取資料,沒釋放鎖之前,其他并行進入的線程會等待100ms,再重新去緩存取資料。這樣就防止都去資料庫重複取資料,重複往緩存中更新資料情況出現。

3)當然這是簡化處理,理論上如果能根據key值加鎖就更好了,就是線程A從資料庫取key1的資料并不妨礙線程B取key2的資料,上面代碼明顯做不到這點。

12.3 緩存雪崩

  描述:

緩存雪崩是指緩存中資料大批量到過期時間,而查詢資料量巨大,引起資料庫壓力過大甚至down機。和緩存擊穿不同的是,緩存擊穿指并發查同一條資料,緩存雪崩是不同資料都過期了,很多資料都查不到進而查資料庫。

解決方案:

1)緩存資料的過期時間設定随機,防止同一時間大量資料過期現象發生。

2)如果緩存資料庫是分布式部署,将熱點資料均勻分布在不同搞得緩存資料庫中。

3)設定熱點資料永遠不過期。

一般避免以上情況發生我們從三個時間段去分析下:

事前:Redis 高可用,主從+哨兵,Redis cluster,避免全盤崩潰。

事中:本地 ehcache 緩存 + Hystrix 限流+降級,避免 MySQL 被打死。

事後:Redis 持久化 RDB+AOF,一旦重新開機,自動從磁盤上加載資料,快速恢複緩存資料。

繼續閱讀