分佈式系統中緩存常見問題與解決方案(1)

緩存做爲DB前的一道防線,過濾了絕大部分DB請求,保障業務系統的高性能與高可用。redis

一樣的,特別是高度依賴緩存的分佈式系統,緩存設計若是不合理,輕則浪費機器資源,重則 1.緩存污染,即緩存與DB數據不一致,影響數據正常展現,如果在交易鏈路,則會形成資損;2.難以承載大流量,致使服務雪崩。數據庫

下面總結了分佈式系統中,緩存設計的常見問題與相應解法。緩存

1.緩存穿透

緩存穿透,即請求了緩存中不存在的數據,致使請求打到DB,形成DB負載變高。若是出現大量緩存穿透請求,一是說明緩存命中率低,浪費機器資源;二是會存在將DB鏈接打滿、服務宕機的風險。bash

應對緩存擊穿有兩種經常使用方案:(1)對於無效數據,緩存中使用佔位符存儲;(2)使用布隆過濾器進行前置攔截。網絡

1.1 緩存佔位符

簡單來講,當數據無效 or 不存在時,使用特殊佔位符進行緩存。下一次請求來時,不須要走到DB,直接返回。併發

1.2 布隆過濾器(Bloom Filter)

若是無效數據量比較大,使用佔位符的策略,會浪費大量內存資源。這種狀況可使用布隆過濾器。異步

布隆過濾器的原理:使用bitMap進行數據存儲,使用多個hash函數計算數據位。hash計算出入參的下標,並標記爲1。當計算出來的下標對應的bitMap都爲1時,則認爲該數據存在。反之,則不存在。分佈式

布隆過濾器的特性:函數

  • 使用bitMap存儲數據,內存佔用極低;
  • 能肯定一個值必定不存在,但不能肯定一個值必定存在(小几率事件,由於存在hash碰撞的因素)。知足緩存過濾的需求。

以下圖所示,入參爲商品productId,使用3個hash函數(H1,H2,H3)計算其hash值,做爲bitMap的下標。性能

productId1,標誌位爲[0,4,7],product2標誌位爲[2,4,10]

這時查詢請求進來,查productId3,假設計算出bitMap下標爲[2,4,9],對應占位爲[1,1,0],則productId3不存在。

使用布隆過濾器做爲緩存的前置過濾,能夠有效過濾掉無效數據請求。

兩種方案對比

佔位符:代碼實現簡單,數據時效性高,內存佔用較高,適用於無效數據量小的場景。

布隆過濾器:代碼實現複雜,數據時效性低,內存佔用低,適用於無效數據量大,且數據時效性要求不高的場景。

2.緩存擊穿

緩存擊穿,即某個熱點緩存失效後(緩存過時),該熱點key的請求直接打到DB,形成DB壓力瞬間增大。

解決方案:(1)熱點緩存永不過時;(2)加互斥鎖

2.1熱點緩存永不過時

通常是經過計算出邏輯上的過時時間,好比活動、商品過時時間endTime,再設置緩存過時時間爲endTime,保證在邏輯過時時間內,緩存一直有效。

固然若是內存滿了,緩存會啓動淘汰機制,視狀況會可能會淘汰永久緩存。相應解法以下:

方案一:作熱點緩存隔離,熱點緩存與普通緩存放在不一樣集羣,內存容量不受普通緩存數據影響;

方案二:緩存不作永不過時設置,而是設置過時時間,同時業務代碼加入緩存更新邏輯,在緩存過時前,更新緩存。實現方式能夠是mq、延時mq、異步線程等。

2.2 互斥鎖

查DB操做前加鎖,同一時刻只能有一個請求打到DB,其餘請求等待重試。該方案引入分佈式鎖,將DB壓力轉移到分佈式鎖上,實現簡單,但存在請求過大時,等待時間過長,線程被打滿的風險。

示例代碼:

private finial static String QUERY_LOCK = "lock_"

public Object getDate(String key){
    Object value = redis.get(key);
    if (value == null) {
        //設置分佈式鎖
        if (redis.setnx(QUERY_LOCK + key, 1, time)) {
            value = db.get(key);
            redis.set(key, value, time);
            redis.delete(QUERY_LOCK + key);
        } else {
            sleep(500);
            return getDate(key);
        }
    }
    return value;
}
複製代碼

3.緩存雪崩

緩存雪崩,即大量key在同一時間內同時過時,形成大量請求打到DB。

解法比較簡單,在設置緩存時,在基礎過時時間上,隨機浮動加減時間,避免緩存在同一時間失效。同時能夠在DAO層 or DB中間件 加入限流,避免瞬時大流量打垮DB。

4.緩存一致性

緩存一致性,即緩存數據與DB數據的一致性。引入緩存後,同一份數據分佈在兩處,因爲網絡IO、數據庫事物、併發操做等因素,會形成緩存與DB數據不一致的問題。

而形成緩存數據不一致問題的主要緣由,基本都是由數據更新+併發操做致使。 簡單舉例:

算了,感受緩存一致性問題都能單開一章分析了。那麼下面的小結咱仍是留到後面再開新章節吧,感謝看到這裏的各位。

4.1 更新緩存的常見方案

4.2 緩存一致性保障方案

5.緩存高可用

6.超熱點緩存

相關文章
相關標籤/搜索