Cache架構設計

Cache策略

  • 定時過時策略
    1. 定時過時的好處是Cache節點的個數符合實際需求,不會形成資源濫用和服務器壓力
    2. 定時過時適合訪問量較大,實時性要求不高的狀況
    3. 若是訪問量小,定時過時會形成Cache命中率低,若是實時性要求高,過時間隔過小,Cache的意義就不大
    4. 適用狀況 : 實時性低
  • 全量刷新策略
    1. 全量刷新的好處是Cache命中率高,Cache實時性高
    2. 全量數據相比那些Cache key值設置很差的非全量Cache,可能反而更小
    3. 全量刷新的弊端是有可能形成服務器的壓力,若是數據使用率低,就是對資源的濫用
    4. 全量刷新適合數據量小或者數據使用率高的應用
    5. 適用狀況 : 數據量小
  • 定時刷新策略
    1. 定時刷新的Cache節點個數和Cache大小成正比,須要綜合考慮Cache命中率和數據量設定節點個數
    2. 節點數過大會形成Cache龐大,太小會形成命中率低
    3. 定時刷新的頻率和實時性成正比
    4. 定時刷新對服務器資源有必定的濫用
    5. 須要開發人員瞭解具體服務的訪問量數據量,制定合適的節點個數與刷新頻率
    6. 使用狀況 : 其餘策略沒法知足
  • 定時過時+磁盤持久化策略
    1. 過時Cache存磁盤文件,系統下線全部cache持久化
    2. 分佈式Cache機制,互相備份,錯開重啓
    3. 能夠在必定條件下捨棄數據庫
  • Cache與訪問量,數據量,定時性的關係
    1. 訪問量大,數據量大,實時性高,可使用複雜的定時刷新,還須要根據實際狀況作優化
    2. 訪問量小,數據量大,實時性高,可使用定時刷新或不用Cache
    3. 數據量小,實時性高,可使用全量刷新
    4. 訪問量大,數據量大,實時性低,可使用定時過時
    5. 訪問量小,數據量大,實時性低,可使用定時過時或者定時刷新

智能Cache策略

  • UserPreference cache
  • Subscription cache
  • 分時間段的Cache,某些時間段的某些cache不過時,須要經過分析流量制定時間段

穿透優化

  • 緩存穿透
    1. 發生大量不存在的key的訪問,會加劇對數據庫層的壓力
  • 優化方法
    1. 緩存空對象key:null
      1. 空對象使用一個比較短的過時時間
      2. 用主動刷新策略應對key又被存入數據庫的狀況
      3. 實現成本低,佔用內存不可控(由非法key和合法key的比例決定)
    2. 布隆過濾器攔截
      1. BloomFilter緩存全部存在的key,進行第一層過濾
      2. 會下降緩存的性能,實現成本高,佔用內存可控
    3. 不使用傳統的低性能的數據庫

無底洞優化

  • 無底洞現象
    1. 分佈式存儲隨着節點數的增長以及key的隨機分佈,批量操做的網絡傳輸次數怎加形成性能不增反減
  • 優化方法
    1. 串行IO
      1. 先將批量查詢的key所在的節點作mapping
      2. 屬於相同節點的key合併一組,循環的全部組進行查詢
    2. 並行IO
      1. 對串行IO做多線程處理
    3. hash tag
      1. 將相同hash tag的數據存儲在同一個節點
      2. 一次批量查詢只操做相同hash tag的key
      3. 容易產生數據分佈不均衡

緩存重建優化

  • 問題
    1. 高併發的熱點key+數據對象大重建緩慢
    2. 數據過時等狀況形成大量線程來重建緩存,使得服務崩潰
  • 優化方法
    1. 永不過時或者timeToIdle+主動更新
    2. 互斥鎖:Redis能夠用setnx實現
    3. 用戶請求不重建緩存,用單獨線程合併用戶請求重建緩存

熱點key集中化優化

其餘等待解決疑問

  • Server resource的個數大小如何定
  • resourcePool的個數與大小
  • Manage the CacheManager/Cahce/Entity
  • load balance
  • Thread Pools線程池
  • key生成策略

CacheManager/Cache等實例數量與大小的考慮

  • server resource & resource pool
    1. server resource能夠多設置幾個,好比每一個1-5G這樣,設置5個備用,每一個能夠給一個CacheManager使用
    2. 一個server resource裏能夠設置一個或多個resourcePool用於clusteredShared,一個或多個resourcePool用於clusteredDedicated,這個要根據實際需求
    3. 一旦clusted端創建了CacheManager,此CacheManager所佔用的resourcePool就會被分配給這個CacheManager,因此resourcePool的大小應該更具項目實際狀況設置,以避免形成資源浪費
    4. 一個pool滿了,就使用下一個,而不是增長它的大小,否則會影響全部使用者
    5. 也可使得pool的大小動態獲取,而不是hard code
  • CacheManager
    1. 不一樣的業務模塊建立不一樣的CacheManager實例,能夠保持業務模塊獨立性
      1. 好比說能夠單獨清除一個CacheManager的全部Cache
    2. 多個CacheManager,配置代碼在不一樣項目的複用會出現問題,如何解決?
      1. 用一個項目建立CacheManager,其餘項目用缺省的方式鏈接CacheManager
    3. 單個CacheManager和多個CacheManager的性能問題?多個CacheManager真的必要麼?
  • Cache
    1. 不一樣的業務模塊建立不一樣的Cache實例,能夠保持業務模塊獨立性
      1. 不一樣的業務模塊可使用不一樣的key規則
      2. 能夠獨立的管理cache,好比刪除等操做
      3. 能夠更合理的定製Cache大小,提升cache命中率
      4. 能夠更合理的定製Expiry
    2. 經過不一樣的Expiry策略建立不一樣的Cache實例
      1. 方便開發,無須每次都建立新的cache
    3. clusteredDedicated
      1. 必須指定cache的大小,不適合producer/consumer的方式,由於consumer必須知道producer設置的大小
      2. 可以更好的更具實際須要利用內存資源
    4. clusteredShared
      1. 不須要指定每一個cache大小,方便producer/consumer主從互換
      2. Shared pool的大小必須足夠大,並且基本不變,才能方便使用,這樣便會形成內存的浪費
      3. Shared pool的變化會形成全部producer/consumer的配置要變
    5. clustered繼承
      1. 解決了clusteredDedicated的問題
      2. 可是若是有兩個以上的producer或者spring cache那樣本身也是producer,仍是必須統一配置
  • 不方便的地方
    1. spring cache無須手動create cache,可是ehcache clustered必須手動,由於每一個cache的配置更靈活
    2. withCache/createCache建立新cache,必須用autoCreate,在原來的CacheManager實例裏建立新的cache而且鏈接
  • 動態cache配置機制
  • 多個Cache不一樣項目的配置
    1. 配置服務化[不推薦]
      1. 將配置信息封裝成配置對象
      2. service提供獲取配置對象服務
      3. 形成client項目依賴service或者cache項目
    2. 主從互換
      1. service與client都去判斷cluster端是否存在cache,若是不存在,那麼建立,不然繼承
      2. 形成cache manage也沒法繼承
      3. 沒法保證service與client建立cache時使用相同配置
      4. 適合clusteredShared
      5. 不適合clusteredDedicated的緣由是client必須知道service端設置的大小
      6. 若是有兩個以上的producer,也不適合clustered繼承
    3. 完美主從互換[跨項目組的狀況下建議使用]
      1. 方法1: service提供Cache配置服務,client獲取配置建立cache,配置服務使得service必須有服務提供
      2. 方法2: common jar的形式保證建立cache時使用相同配置
      3. 方法3: service方提供client代碼,client利用client代碼建立cache
      4. 保證service與client建立cache時使用相同配置
      5. service必須知道本身的cache的配置,沒法使用動態cache配置機制
      6. 須要動態cache配置的時候只適合clusteredShared,不然可使用clusteredDedicated
      7. 這個工做須要額外開發,很麻煩啊,兩害取其輕,仍是使用clusteredShared+動態pool size吧,一點點浪費總比不可控也增長開發/維護難度好
    4. service主導[不推薦]
      1. client判斷cluster端是否存在cache,若是不存在,那麼建立,不然繼承
      2. service判斷cluster端配置是否符合本身要求,如何不符合,刪除cache從新建立,不然直接建立
      3. 可是必須全部cache manager close()
      4. 適合clusteredDedicated
相關文章
相關標籤/搜索