第5章 メモリーの管理

Data Grid がエントリーを保存するデータコンテナーを設定します。キャッシュエントリーのエンコーディングを指定し、データをオフヒープメモリーに保存し、エビクションまたは有効期限ポリシーを使用してアクティブなエントリーのみをメモリーに維持します。

5.1. エビクションおよびの有効期限の設定

エビクションと有効期限は、古い未使用のエントリーを削除してデータコンテナーをクリーンアップするための 2 つの戦略です。エビクションと有効期限は同じですが、重要な違いがいくつかあります。

  • ✓ エビクションを使用すると、コンテナーが設定されたしきい値より大きくなったときにエントリーを削除することで、Data Grid がデータコンテナーのサイズを制御できます。
  • ✓ 有効期限により、エントリーの存在が制限されます。Data Grid はスケジューラーを使用して、期限切れのエントリーを定期的に削除します。有効期限が切れていても削除されていないエントリーは、アクセスするとすぐに削除されます。この場合、期限切れのエントリーに対する get() 呼び出しは、"null" 値を返します。
  • ✓ エビクションは Data Grid ノードのローカルです。
  • ✓有効期限は Data Grid クラスター全体で実行されます。
  • ✓ エビクションと有効期限を一緒に使用することも、個別に使用できます。
  • infinispan.xml でエビクションおよび有効期限を宣言型で設定し、エントリーのキャッシュ全体のデフォルトを適用できます。
  • ✓ 特定のエントリーの有効期限設定を明示的に定義できますが、エントリーごとにエビクションを定義することはできません。
  • ✓ エントリーを手動でエビクトし、有効期限を手動でトリガーできます。

5.1.1. エビクション

エビクションにより、メモリーからエントリーを削除して、データコンテナーのサイズを制御できます。エビクションは、一度に 1 つのエントリーをデータコンテナーから破棄し、そのエントリーが実行するノードに対してローカルにあります。

重要

エビクションはメモリーからエントリーを削除しますが、永続的なキャッシュストアからは削除しません。Data Grid はそれらをエビクトし、データの一貫性を防ぐために、永続キャッシュストアを設定する必要があります。

Data Grid エビクションは、以下の 2 つの設定に依存します。

  • データコンテナーの最大サイズ。
  • エントリーを削除するストラテジー。

データコンテナーのサイズ

Data Grid を使用すると、エントリーを Java ヒープまたはネイティブメモリー (off-heap) に保存し、データコンテナーに最大サイズを設定できます。

次の 2 つの方法のいずれかでデータコンテナーの最大サイズを設定します。

  • エントリーの合計数 (max-count)。
  • メモリーの最大量 (max-size)。

    メモリー量に基づいてエビクションを実行するには、バイト単位で最大サイズを定義します。このため、application/x-protostream などのバイナリーストレージ形式でエントリーをエンコードする必要があります。

キャッシュエントリーのエビクト

memory を設定する場合、Data Grid はデータコンテナーの現在のメモリー使用量を概算します。エントリーが追加または変更されると、Data Grid はデータコンテナーの現在のメモリー使用量を最大サイズと比較します。サイズが最大値を超えると、Data Grid はエビクションを実行します。

エビクションは、最大サイズを超えるエントリーを追加するスレッドですぐに行われます。

例として以下の設定を見てみましょう。

<memory max-count="50"/>

この場合、キャッシュの合計は 50 個になります。キャッシュがエントリーの合計数に達すると、書き込み操作によって Data Grid がトリガーされ、エビクションが実行されます。

エビクションストラテジー

ストラテジーは、Data Grid のエビクションを実行する方法を制御します。エビクションは手動で実行することも、Data Grid を以下のいずれかを実行するように設定したりできます。

  • 古いエントリーを削除して、新しいエントリー用の領域を作成します。
  • ContainerFullException を出力し、新規エントリーが作成されないようにします。

    例外エビクションストラテジーは、2 フェーズコミットを使用するトランザクションキャッシュでのみ動作しますが、1 フェーズコミットまたは同期の最適化とは関係しません。

注記

Data Grid には、TinyLFU と呼ばれる Least Frequently Used (LFU) キャッシュ置換アルゴリズムのバリエーションを実装する Caffeine キャッシングライブラリーが含まれています。オフヒープストレージの場合、Data Grid は LeastRecent Used (LRU) アルゴリズムのカスタム実装を使用します。

5.1.1.1. Data Grid キャッシュのエントリー数の合計設定

キャッシュエントリーのデータコンテナーのサイズを合計エントリー数に制限します。

手順

  1. 適切なストレージ形式で Data Grid キャッシュエンコーディングを設定します。
  2. Data Grid がエビクションを実行する前にキャッシュを含めることができるエントリーの合計数を指定します。

    • 宣言型: max-count 属性を設定します。
    • Programmatic: maxCount() メソッドを呼び出します。
  3. Data Grid がエントリーを削除する方法を制御するようにエビクションストラテジーを設定します。

    • declarative: when-full 属性を設定します。
    • プログラム: whenFull() メソッドを呼び出します。

宣言型設定

<local-cache name="maximum_count">
  <encoding media-type="application/x-protostream"/>
  <memory max-count="500" when-full="REMOVE"/>
</local-cache>

プログラムによる設定

ConfigurationBuilder cfg = new ConfigurationBuilder();

cfg
  .encoding()
    .mediaType("application/x-protostream")
  .memory()
    .maxCount(500)
    .whenFull(EvictionStrategy.REMOVE)
  .build());

5.1.1.2. Data Grid キャッシュの最大メモリー容量の設定

キャッシュエントリーのデータコンテナーのサイズを最大メモリー量に制限します。

手順

  1. バイナリーエンコーディングをサポートするストレージ形式を使用するように Data Grid キャッシュを設定します。

    バイナリーストレージ形式を使用して、メモリーの最大量に基づいてエビクションを実行する必要があります。

  2. Data Grid がエビクションを実行する前にキャッシュが使用できるメモリーの最大量をバイト単位で設定します。

    • Declarativ 宣言型: max-size 属性を設定します。
    • プログラム: maxSize() メソッドを使用します。
  3. 任意で、測定のバイト単位を指定します。デフォルトは B(バイト単位) です。サポートされるユニットの設定スキーマを参照してください。
  4. Data Grid がエントリーを削除する方法を制御するようにエビクションストラテジーを設定します。

    • declarative: when-full 属性を設定します。
    • プログラム: whenFull() メソッドを使用します。

宣言型設定

<local-cache name="maximum_size">
  <encoding media-type="application/x-protostream"/>
  <memory max-size="1.5GB" when-full="REMOVE"/>
</local-cache>

プログラムによる設定

ConfigurationBuilder cfg = new ConfigurationBuilder();

cfg
  .encoding()
    .mediaType("application/x-protostream")
  .memory()
    .maxSize("1.5GB")
    .whenFull(EvictionStrategy.REMOVE)
  .build());

5.1.1.3. エビクションの例

エビクションをキャッシュ定義の一部として設定します。

デフォルトのメモリー設定

エビクションは有効になっていません。これはデフォルト設定です。Data Grid は、キャッシュエントリーを JVM ヒープのオブジェクトとして保存します。

<distributed-cache name="default_memory">
  <memory />
</distributed-cache>

エントリーの合計数に基づくエビクション

Data Grid は、キャッシュエントリーを JVM ヒープのオブジェクトとして保存します。エビクションは、データコンテナーに 100 エントリーがあり、Data Grid が新規エントリーを作成する要求を取得すると発生します。

<distributed-cache name="total_number">
  <memory max-count="100"/>
</distributed-cache>

エビクションベースの最大サイズ (バイト単位)

Data Grid は、キャッシュエントリーを byte[] 配列として保存します (例: application/x-protostream 形式)。

以下の例では、データコンテナーのサイズが 500 MB(メガバイト) に達すると、Data Grid はエビクションを実行し、新規エントリーを作成する要求を取得します。

<distributed-cache name="binary_storage">
  <!-- Encodes the cache with a binary storage format. -->
  <encoding media-type="application/x-protostream"/>
  <!-- Bounds the data container to a maximum size in MB (megabytes). -->
  <memory max-size="500 MB"/>
</distributed-cache>

オフヒープストレージ

Data Grid は、キャッシュエントリーをバイトとしてネイティブメモリーに保存します。エビクションは、データコンテナーに 100 エントリーがあり、Data Grid が新規エントリーを作成する要求を取得すると発生します。

<distributed-cache name="off_heap">
  <memory storage="OFF_HEAP" max-count="100"/>
</distributed-cache>

例外ストラテジーを使用したオフヒープストレージ

Data Grid は、キャッシュエントリーをバイトとしてネイティブメモリーに保存します。データコンテナーに 100 エントリーがあり、Data Grid が新規エントリーを作成する要求を取得すると、例外が出力され、新しいエントリーは許可されません。

<distributed-cache name="eviction_exception">
  <memory storage="OFF_HEAP" max-count="100" when-full="EXCEPTION"/>
</distributed-cache>

手動エビクション

Data Grid は、キャッシュエントリーを JVM ヒープのオブジェクトとして保存します。エビクションは有効になっていませんが、evict() メソッドを使用して手動で実行されます。

ヒント

この設定は、パッシベーションを有効にし、エビクションを設定しない場合に警告メッセージを防ぎます。

<distributed-cache name="eviction_manual">
  <memory when-full="MANUAL"/>
</distributed-cache>

エビクションによるパッシベーション

パッシベーションは、Data Grid がエントリーをエビクトする際にキャッシュストアにデータを永続化します。パッシベーションを有効にすると、以下のようにエビクションを常に有効にする必要があります。

<distributed-cache name="passivation">
  <persistence passivation="true">
   <!-- Persistence configuration goes here. -->
  </persistence>
  <memory max-count="100"/>
</distributed-cache>

5.1.2. 有効期限

以下のいずれかの時間制限に達すると、キャッシュからエントリーが削除されます。

有効期間
エントリーが存在することができる最大時間を設定します。
最大アイドル

エントリーがアイドル状態のままになる期間を指定します。エントリーに対して操作が行われない場合は、アイドル状態になります。

重要

現在、最大アイドルの有効期限は永続キャッシュストアによるキャッシュ設定をサポートしません。

例外ベースのエビクションポリシーで有効期限を使用する場合、期限切れの状態ではなく、データコンテナーのサイズに対して削除されないエントリーはキャッシュ数から削除されています。

5.1.2.1. 有効期限の仕組み

有効期限を設定する場合、Data Grid はエントリーが期限切れになるタイミングを決定するメタデータを持つキーを保存します。

  • 有効期限は、creation タイムスタンプと lifespan 設定プロパティーの値を使用します。
  • 最大アイドルは、last used タイムスタンプと max-idle 設定プロパティーの値を使用します。

Data Grid は、有効期限または最大アイドルメタデータが設定されているかどうかを確認し、値と現在の時間を比較します。

(creation + lifespan < currentTime) または (lastUsed + maxIdle < currentTime) の場合、Data Grid はエントリーが期限切れであると検出します。

有効期限は、有効期限リーパーによってエントリーがアクセスまたは検出されるたびに発生します。

たとえば、k1 は最大アイドル時間に到達し、クライアントは Cache.get(k1) 要求を作成します。この場合、Data Grid はエントリーが期限切れであることを検出し、データコンテナーから削除します。Cache.get()null を返します。

Data Grid はキャッシュストアのエントリーも期限切れになりますが、ライフサイクルの有効期限のみになります。最大アイドル有効期限はキャッシュストアでは機能しません。キャッシュローダーの場合、ローダーは外部ストレージからしか読み取ることができないため、Data Grid はエントリーを期限切れにすることはできません。

注記

Data Grid は、期限切れのメタデータを、long プリミティブデータタイプとしてキャッシュエントリーに追加します。これにより、32 バイトだけにキーのサイズが増える可能性があります。

5.1.2.2. 有効期限リーパー

Data Grid は、定期的に実行されるリーパースレッドを使用して、期限切れのエントリーを検出して削除します。有効期限により、アクセスされなくなった期限切れのエントリーが確実に削除されるようにします。

Data Grid の ExpirationManager インターフェイスは、有効期限リーパーを処理し、processExpiration() メソッドを公開します。

場合によっては、processExpiration() を呼び出すことで、有効期限リーパーを無効にし、エントリーを手動で期限切れにすることができます。たとえば、メンテナンススレッドが定期的に実行するカスタムアプリケーションでローカルキャッシュモードを使用している場合です。

重要

クラスター化されたキャッシュモードを使用する場合は、有効期限リーパーを無効にしないでください。

キャッシュストアを使用する場合は、Data Grid は常に有効期限のリーパーを使用します。この場合、無効にすることはできません。

5.1.2.3. 最大アイドルキャッシュおよびクラスター化キャッシュ

最大アイドル有効期限はキャッシュエントリーの最後のアクセス時間に依存するため、クラスター化されたキャッシュモードにはいくつかの制限があります。

有効期限が切れると、キャッシュエントリーの作成時間は、クラスター化されたキャッシュ全体で一貫した値を提供します。たとえば、k1 の作成時間は、常にすべてのノードで同じです。

クラスター化されたキャッシュを使用した最大アイドル有効期限のため、エントリーに対する最終アクセス時間は、常にすべてのノードで同じではありません。クラスター全体で相対アクセス時間が同じになるように、Data Grid はキーへのアクセス時に、すべての所有者に touch コマンドを送信します。

Data Grid が送信する touch コマンドには、以下の考慮事項があります。

  • Cache.get() リクエストは、すべての touch コマンドが完了するまで返されません。この同期動作により、クライアント要求のレイテンシーが長くなります。
  • touch コマンドは、すべての所有者のキャッシュエントリーの recently accessed メタデータも更新します。
  • scattered キャッシュモードの場合、Data Grid はプライマリーおよびバックアップ所有者のみではなく、touch コマンドをすべてのノードに送信します。

関連情報

  • 最大アイドル有効期限はインバリデーションモードでは機能しません。
  • クラスター化されたキャッシュでの反復は、最大アイドル時間制限を超過した期限切れのエントリーを返すことができます。この動作は、反復中にリモート呼び出しが実行されないため、パフォーマンスが向上します。また、繰り返しは期限切れのエントリーを更新しないことに注意してください。

5.1.2.4. 有効期限の例

Data Grid を設定してエントリーを期限切れにすると、以下のアイドル期間と最大アイドル時間を設定できます。

  • キャッシュ内のすべてのエントリー (キャッシュ全体)infinispan.xml でキャッシュ全体の有効期限を設定できます。または、ConfigurationBuilder を使用してプログラムで設定できます。
  • エントリーごとに優先され、キャッシュ全体の有効期限の値よりも優先されます。エントリーの作成時に特定のエントリーの有効期限を設定します。
注記

キャッシュエントリーの lifespan と最大アイドル時間の値を明示的に定義すると、Data Grid はキャッシュエントリーとともにクラスター全体でこれらの値を複製します。同様に、キャッシュストアを設定する場合は、Data Grid はエントリーと共に有効期限の値を永続化します。

すべてのキャッシュエントリーの有効期限の設定

2 秒後にすべてのキャッシュエントリーを期限切れにします。

<expiration lifespan="2000" />

最後のアクセス時間後にすべてのキャッシュエントリーを 1 秒後に期限切れにします。

<expiration max-idle="1000" />

interval 属性を使用して期限切れリーパーを無効にし、最後のアクセス時刻の 1 秒後にエントリーを手動で期限切れにします。

<expiration max-idle="1000" interval="-1" />

最後のアクセス時間から 5 秒または 1 秒後にすべてのキャッシュエントリーの有効期限が切れるので、これは常に最初に発生します。

<expiration lifespan="5000" max-idle="1000" />

キャッシュエントリーの作成時に有効期限の設定

次の例は、キャッシュエントリーを作成するときにライフスパンと最大アイドル値を設定する方法を示しています。

// Use the cache-wide expiration configuration.
cache.put("pinot noir", pinotNoirPrice); 1

// Define a lifespan value of 2.
cache.put("chardonnay", chardonnayPrice, 2, TimeUnit.SECONDS); 2

// Define a lifespan value of -1 (disabled) and a max-idle value of 1.
cache.put("pinot grigio", pinotGrigioPrice,
          -1, TimeUnit.SECONDS, 1, TimeUnit.SECONDS); 3

// Define a lifespan value of 5 and a max-idle value of 1.
cache.put("riesling", rieslingPrice,
          5, TimeUnit.SECONDS, 1, TimeUnit.SECONDS); 4

Data Grid 設定ですべてのエントリーの有効期間値が 1000 と定義されている場合は、先行する Cache.put() 要求により、エントリーが期限切れになります。

1
1 秒後。
2
2 秒後。
3
最後のアクセス時間から 1 秒後。
4
最後のアクセス時間の 5 秒後または 1 秒後のいずれか早い方。