20

過去数週間、グアバのMapMakerを使用して、理想的なキャッシュの実装を見つけようとしてきました。私の思考プロセスに従うために、ここここで私の前の 2 つの質問を参照してください。

学んだことを踏まえて、次の試みはソフト値を捨てて maximumSize と expireAfterAccess を使用することです。

ConcurrentMap<String, MyObject> cache = new MapMaker()
        .maximumSize(MAXIMUM_SIZE)
        .expireAfterAccess(MINUTES_TO_EXPIRY, TimeUnit.MINUTES)
        .makeComputingMap(loadFunction);

どこ

Function<String, MyObject> loadFunction = new Function<String, MyObject>() {
   @Override
   public MyObject apply(String uidKey) {
      return getFromDataBase(uidKey);
   }
};

ただし、私がまだ取り組んでいる残りの 1 つの問題は、この実装では、到達可能性が高い場合でも、時間切れになるとオブジェクトが削除されることです。これにより、同じ UID を持つ複数のオブジェクトが環境内に浮かぶ可能性がありますが、これは望ましくありません (私が達成しようとしているのは、正規化として知られていると思います)。

したがって、唯一の答えは、データオブジェクトがまだメモリ内にあるかどうかを確認できるインターナーとして機能する追加のマップを用意することです。

ConcurrentMap<String, MyObject> interner = new MapMaker()
        .weakValues()
        .makeMap();

load 関数は次のように修正されます。

Function<String, MyObject> loadFunction = new Function<String, MyObject>() {
   @Override
   public MyObject apply(String uidKey) {
      MyObject dataObject = interner.get(uidKey);
      if (dataObject == null) {
         dataObject = getFromDataBase(uidKey);
         interner.put(uidKey, dataObject);
      }
      return dataObject;
   }
};

ただし、キャッシュに 1 つではなく 2 つのマップを使用するのは効率が悪いようです。これにアプローチするより洗練された方法はありますか?一般的に、私はこれを正しい方法で行っていますか、それともキャッシュ戦略を再考する必要がありますか?

4

2 に答える 2

8

2 つのマップが効率的かどうかは、getFromDatabase() のコストが高いことと、オブジェクトの大きさに完全に依存します。このようなことをするのは、すべての合理的な境界から外れているようには見えません。

実装に関しては、マップをわずかに異なる方法でレイヤー化して、必要な動作を取得し、優れた同時実行性を維持できるようです。

  1. 弱い値で最初のマップを作成し、計算関数 getFromDatabase() をこのマップに配置します。
  2. 2 番目のマップは期限切れのもので、これも計算していますが、この関数は最初のマップから取得するだけです。

2 番目のマップからすべてのアクセスを行います。

つまり、期限切れマップは、オブジェクトの最近使用されたサブセットをメモリに固定するように機能しますが、弱参照マップは実際のキャッシュです。

-dg

于 2011-07-25T06:39:54.203 に答える
0

ここでは全体像がわかりませんが、2 つのことがあります。

  1. このステートメントを考えると、「この実装は、時間切れになると、強く到達可能なオブジェクトであってもオブジェクトを追い出します。これにより、環境内に同じ UID を持つ複数のオブジェクトが浮遊する可能性があります。これは望ましくありません。」--weakKeys()を使用するだけでよく、時間指定またはサイズベースの削除は使用しないようです。

  2. または、これに「インターナー」を持ち込みたい場合は、実数を使用しInterners.newWeakInternerます。

于 2011-07-25T19:40:37.350 に答える