天天看點

高性能緩存方案實踐總結

作者:一隻程式猿粑粑
在實際項目中為了提高系統運作效率,往往把部配置設定置性的資料放在應用記憶體或高性能緩存伺服器中,減少網絡調用,減少資料庫調用,以此在作為提高性能的一種方案。

遠端緩存

方案描述

項目中可通過搭建高性能緩存伺服器的方式,實作應用緩存的集中管理;redis和zookeeper可作為技術選型。該方案基本可以作為微服務大環境下的最常用方案了。

高性能緩存方案實踐總結

即:

1、管理端通過維護資料庫将配置的資訊維護在資料庫中,完成對資料的全生命周期管理;

2、管理端通過釋出配置的方式将配置資訊釋出到緩存伺服器中;

3、應用服務在業務執行過程中,用到配置資訊時,通過用戶端的方式到緩存服務中擷取;

優缺點

優點:可實作緩存資訊的集中管理,減少各個應用的記憶體占用;

缺點:緩存伺服器需要叢集部署,增加客戶伺服器開銷;zk和redis也需要相關的運維更新;有部分的網絡開銷(高性能情況下可忽略不計);

本地緩存

與遠端緩存相比較,該方案将配置資訊儲存在資料庫中,各個應用服務通過加載自己加載資料庫資料到本地記憶體中的方式完成本地緩存建立;

高性能緩存方案實踐總結

1、管理端通過維護資料庫将配置的資訊維護在資料庫中,完成對資料的生命周期管理;

2、應用服務啟動時根據應用的業務屬性,加載自己需要的參數資訊到應用本地緩存中;

3、應用服務在業務執行過程中,直接使用本地緩存中的資料,如果本地緩存中沒有,則再到資料庫中自行裝載;

4、當管理端完成對資料庫的配置更新時,需要通知相關的應用服務;應用服務接收到緩存更新信号時則主動到資料庫中重新裝載配置資訊到本地緩存;

優點:緩存使用無網絡開銷;使用友善,無其他中間件依賴;普通的功能性開發即可;

缺點:功能複雜,各個應用獨立占用記憶體,造成伺服器記憶體壓力大;

二級緩存方案

将管理端的配置資訊在系統啟動時裝入記憶體。

主要是實作兩級記憶體的劃分,資料庫映射和計算内容;

其中記憶體映射是根據資料庫表結構,從資料庫中根據應用标示加載起來的資訊,每一塊記憶體資訊對應了資料庫中的一個表,該部分完成後,在交易過程中通過表之間的關系及交易需要的參數,将資料庫表之間的關聯關系整合到計算記憶體中,交易過程直接使用計算記憶體資料,提高交易處理性能。

其中記憶體映射層使用ConcurrentHashMap作為存儲單元,存儲應用對應的整體資料;計算記憶體使用caffeine cache作為緩存處理單元,存儲每一個已經接入的交易需要的資料,并設定失效時間,配置資料失效後重新計算存儲單元的資料形成計算單元記憶體資料。

記憶體映射層存儲資料庫對應的業務相關資訊,計算記憶體層存儲常用的緩存資訊,并根據使用情況自動完成映射層到計算層的轉化。

高性能緩存方案實踐總結

技術實作

ConcurrentHashMap

public abstract class AbstractRouterCache<T> implements IRouterCache {
  public ConcurrentHashMap<String, T> caches = new ConcurrentHashMap<>(100);
  public void updateCache(String key, T cachedValue) {
    caches.put(key, cachedValue);
  }
  public void clearCache() {
    caches.clear();
  }
  public T getCacheValue(String key) {
    return caches.get(key);
  }
}           

CaffeineCache:https://github.com/ben-manes/caffeine

網上資料一搜一大堆,用到的筒子們可以自行搜尋去。

public class ActionCacheService {
  private static Cache<String, ActionCache> mainCache;
  
  static {
    // 為保證交易配置可重複使用,以2小時,10K 為準建立緩存資訊
    mainCache = Caffeine.newBuilder()
      .expireAfterWrite(2, TimeUnit.HOURS)
      .maximumSize(10_000)
      .build();
  }
  
  public static void invalidateMainCache(){
    mainCache.invalidateAll();
  }
  
  /**
  * 從外部控制主動重新整理參數資訊
  *
  * @param servCode
  * @param webServiceId
  */
  public static void refreshActionCache(String servCode, String webServiceId) {
    String key = servCode + "@" + webServiceId;
    mainCache.put(key, buildActionCache(servCode, webServiceId));
  }
  
  /**
  * 從主緩存資訊中擷取交易碼和URI對應的服務資訊,如果緩存中不存在該資訊則重新從資料庫緩存中擷取資訊
  *
  * @param servCode
  * @param webServiceId
  * @return
  */
  public static ActionCache getActionCache(String servCode, String webServiceId) {
    String key = servCode + "@" + webServiceId;
    return mainCache.get(key, bac -> buildActionCache(servCode, webServiceId));
  }
  
  private static ActionCache buildActionCache(String servCode, String webServiceId) {
    ActionCache actionCache = new ActionCache();
    // 業務邏輯處理
    return actionCache;
  }
  
  // 其他程式部分
}           
你看,奇怪的知識是不是又增加了

繼續閱讀