ローカルキャッシュ技術の分析 - Guava Cache | JD Logistics Technical Team

1 はじめに

Java 開発者としては、guava ツールキットについては誰もがあまり馴染みがないと思いますが、ローカル キャッシュ技術である guava キャッシュについては、日常の業務や開発でも誰もがある程度は知っていると思います。次に、この記事では、Google が提供する guava キャッシュについて、さまざまな角度から分析していきます。

2 つのグアバ キャッシュ アプリケーション シナリオ

ローカル キャッシュはデータの読み書きが 1 つのプロセスで行われるため、redis などの分散キャッシュに比べてネットワーク転送の処理が不要でアクセス速度が非常に速いですが、JVM メモリの制限もあり、大量のデータを扱うシナリオでは使用できません。

上記の特性に基づいて、guava キャッシュの主なアプリケーション シナリオは次のとおりです。

  • アクセス速度に対する要件がさらに厳しくなっている
  • 保存されたデータは頻繁には変更されません
  • データ量が少なくメモリ使用量も少ない
  • コレクション全体にアクセスする必要がある
  • リアルタイムではないデータを許容できる

ここでは、パラメータ設定を保存するために guava キャッシュが使用されており、これも上記のアプリケーション シナリオの条件を満たしています。

3 グアバキャッシュの使い方

Guava キャッシュは com.google.common.cache パッケージの下にあります。コア クラスは 2 つあり、1 つはキャッシュの構築に使用される CacheBuilder で、もう 1 つはキャッシュ データの保存に使用されるキャッシュ コンテナーである Cache です。

guava キャッシュを使用するには、まず Maven の依存関係を導入します。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>18.0</version>
</dependency>

次に簡単な例を書きます。

Cache<String, String> localCache = CacheBuilder.newBuilder()
                .initialCapacity(5)
                .maximumSize(10)
                .concurrencyLevel(3)
                .expireAfterWrite(10, TimeUnit.SECONDS)
                .build();

上記の例では、ローカル キャッシュをインスタンス化し、次に初期化パラメータの意味を導入します。
initialCapacity: 内部ハッシュ テーブルの最小容量、つまりキャッシュの初期容量。

MaximumSize: キャッシュの最大キャッシュ サイズ。

concurrencyLevel: 同時実行レベル。同時にキャッシュを操作するスレッドの数としても定義でき、次のように決定されます。

スレッド数がデフォルトで 4 になっていることがわかります。

expireAfterWrite: 書き込み後のキャッシュ更新時間。

キャッシュからデータを取得するメソッドは get(K key, Callable<? extends V>loader) メソッドです。このメソッドの意味は、キー key に従ってデータを取得することです。キーが存在しない場合は、指定された Callable メソッドを実行することによってキャッシュが構築されます。サンプル コードは次のとおりです。

Map<String, Dicdetail> dicDetailMap = ObLocateCache.locateConfigCache.get(key.toString(), new Callable<Map<String, Dicdetail>>() {
                @Override
                public Map<String, Dicdetail> call() throws Exception {
                    return getConfigParameterFromMaster(baseDomain, KeyConstants.WMS5_LOCATE_MANUAL);
                }
            });

キャッシュからのデータの削除は、パッシブ削除とアクティブ削除に分けられます。

1. 受動的削除:

  • データサイズに応じて削除:LRU+FIFO
  • 有効期限に基づいて削除: 指定された時間内にアクセスされませんでした
  • 参照ベースの削除:weakKeys メソッドとweakValues メソッドを使用して、キャッシュがキャッシュ レコードのキーと値への弱い参照のみを保存するように指定します。このようにして、キーと値への強い参照が他にない場合、キーと値のオブジェクトはガベージ コレクターによって回収されます。

2. 以下を積極的に削除します。

//删除指定的key对应数据
cache.invalidate("s");
//将一批对应的数据删除
cache.invalidateAll(Arrays.asList("st","r","ing"));
//全部删除
cache.invalidateAll();

4 ソースコードに従ってグアバキャッシュの保存原理を分析する

guava キャッシュのデータ構造は ConcurrentHashMap のデータ構造に似ていますが、この 2 つの基本的な違いは、ConcurrentMap は追加された要素が削除されるまですべての追加要素を保持することです。対照的に、メモリ使用量を制限するために、guava キャッシュは通常、要素を自動的にリサイクルするように設定されています。

guava キャッシュのコア クラスは LocalCache で、LocalCache は ConcurrentMap インターフェイスを実装します。以下に示すように、セグメント配列があります。

データ取得メソッドのソースコードを下図に示しますが、guava キャッシュの格納原理は、Segment 配列、ReferenceEntry リンク リスト、AtomicReferenceArray 配列から構成されるデータ構造であることがわかります。

データ構造図は次のとおりです。

Segement 配列の長さによって、同時キャッシュの数が決まります。各セグメントは ReentrantLock を継承し、個別のロックを使用します。セグメントへの書き込み操作では、最初にロックを取得する必要があります。書き込み操作部分のソースコードは以下のとおりです。

5 まとめ

この記事では、guava キャッシュのアプリケーション シナリオと簡単な使用法を簡単に説明し、ソース コードを通じて guava キャッシュの保存原理と簡単な読み取りおよび書き込み方法を紹介します。この記事を読むことで、一般的なグアバ キャッシュについて概要を理解できると思います。

著者: JD Logistics Wang Chenwei

出典: JD Cloud 開発者コミュニティ Ziqshuo Tech

RustDesk 1.2: Flutterを使用してデスクトップ版を書き換え、 deepinで告発されたWaylandをサポート V23は2023年に最も需要の多いWSL 8プログラミング言語への適応に成功: PHPは好調、C/C++需要は鈍化 ReactはAngular.jsの瞬間を経験している? CentOS プロジェクトは「誰にでもオープン」であると主張 MySQL 8.1 および MySQL 8.0.34 が正式にリリース Rust 1.71.0 安定版 リリース
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4090830/blog/10089606
おすすめ