この章では、バッキング・マップを使用したCoherenceの記憶域について説明します。この章は次の各項で構成されています。
Coherenceのパーティション(分散)キャッシュ・サービスは、次の3つのレイヤーに分かれています。
クライアント・ビュー: 基礎となるパーティション化されたデータへのアクセスを可能にする仮想レイヤー。この層へのアクセスには、NamedCache
インタフェースが使用されます。このレイヤーでは、NearCache
やContinuousQueryCache
などの統合データ構造も作成できます。
ストレージ・マネージャ: クライアント層からのキャッシュ関連リクエストを処理するサーバー側の層です。実際のキャッシュ・データ(プライマリ・コピーおよびバックアップ・コピー)、およびロック、イベント・リスナー、マップ・トリガーなどに関する情報を格納するデータ構造を管理します。
バッキング・マップ: 実際のデータを格納するサーバー側のデータ構造。
Coherenceでは、出荷状態のまま使用できる多数のバッキング・マップの実装を構成することも、カスタム構成を使用することもできます。基本的に、これらすべてのマップ実装における唯一の制約は、ストレージ・マネージャではキーと値がすべて内部(バイナリ)形式で指定されるということであり、その点に留意する必要があります。内部データとオブジェクト形式との間の変換を処理するため、ストレージ・マネージャでは、BackingMapManagerContext
参照によるバッキング・マップの実装が可能です。
図12-1は、バッキング・マップの概念図です。
ローカル記憶域は、Coherenceで管理されるデータを実際に保存またはキャッシュするデータ構造です。ローカル記憶域を提供するオブジェクトは、同じ標準のコレクション・インタフェースであるjava.util.Map
をサポートする必要があります。Coherenceのローカル記憶域の実装を使用して、レプリケートされたデータや分散データを保存する場合、その機能をバッキング・マップと呼びます。これは、Coherenceがローカル記憶域の実装によって実際に支援(バックアップ)されるためです。その他、ローカル記憶域の一般的な使用法としては、分散キャッシュの前に配置したり、分散キャッシュの後方でバックアップを行うことがあります。
Coherenceは通常、次のいずれかのローカル記憶域の実装を使用しています。
セーフなHashMap: デフォルトのロスレス実装です。ロスレス実装には、JavaのHashtableクラス同様、サイズ制限も自動失効もありません。つまり、自身に含まれるキャッシュ項目を削除する(損失する)ことのない実装です。この特殊なHashMap
実装は、非常に高度なスレッドレベルの並行性にあわせて最適化されています (デフォルト実装にはcom.tangosol.util.SafeHashMap
クラスを、キャッシュ・イベントの送信が必要な実装にはcom.tangosol.util.ObservableHashMap
を使用します。これらの実装はスレッドセーフです)。
ローカル・キャッシュ: デフォルトのサイズ制限または自動失効、あるいはその両方の実装です。ローカル・キャッシュについては後で詳しく説明しますが、ここで覚えておくべき重要な点は、キャッシュ・サイズを制限できること、および一定期間後にキャッシュ項目を自動失効できることです (デフォルト実装にはcom.tangosol.net.cache.LocalCache
を使用します。この実装はスレッド・セーフであり、キャッシュ・イベント、com.tangosol.net.CacheLoader
、CacheStore
、および構成可能でプラッガブルなエビクション・ポリシーがサポートされます)。
読取り/書込みバッキング・マップ: キャッシュ・ミス発生時にデータベースからロードする、キャッシュのデフォルトのバッキング・マップ実装です。読取り専用キャッシュ(コンシューマ・モデル)として構成することも、ライトスルー・キャッシュまたはライトビハインド・キャッシュ(コンシューマ/プロデューサ・モデル)のいずれかとして構成することもできます。ライトスルーおよびライトビハインド・モードは、分散キャッシュ・サービスで使用することのみを目的としています。ニア・キャッシで使用され、ニア・キャッシュと分散キャッシュの同期を維持する必要がある場合には、このバッキング・マップをSeppukuベースのニア・キャッシュと組み合せて使用できます(ニア・キャッシュを無効化する目的で)。ただし、これらの要件を考慮する場合はバージョニングされた実装を使用することをお薦めします(デフォルト実装にはcom.tangosol.net.cache.ReadWriteBackingMap
クラスを使用します)。
バージョニングされたバッキング・マップ: データ・バージョニング・テクニックを利用してデータ処理を最適化する、読取り/書込みバッキング・マップの最適化バージョンです。たとえば、バージョン変更通知を送信するだけでニア・キャッシュを無効化したり、永続的な(データベースの)バージョン情報を一時的な(キャッシュされた)バージョン情報と比較することで、キャッシュされたデータをデータベースに再び書き込む必要があるかどうかを判断できます。バージョニングされた実装を使用すると、読取りの集中するデータと書込みの集中するデータの両方に対する、大規模なクラスタ内での非常にバランスのとれたパフォーマンスを実現できます (デフォルト実装にはcom.tangosol.net.cache.VersionedBackingMap
クラスを使用します。このバッキング・マップでは、オプションでニア・キャッシュ実装としてcom.tangosol.net.cache.VersionedNearCache
を使用できます)。
バイナリ・マップ(Java NIO): 自身の情報をメモリー内(ただしJavaヒープ外)に保存したり、メモリー・マップ・ファイルにも保存できるバッキング・マップ実装です。つまり、Javaヒープ・サイズには影響せず、アプリケーションの一時停止の原因となり得る関連したJVMガベージ・コレクションのパフォーマンスにも影響しないことを意味します。この実装はまた、分散キャッシュのバックアップにも使用できます。これは高可用性を実現するためにバックアップを必要とする、読取り専用(または読取りを主体とする)キャッシュで特に有用です。このバックアップがJavaヒープ・サイズに影響しないにもかかわらず、フェイルオーバー時には瞬時に使用できるためです。
シリアライズ・マップ: マップ自体のデータをディスクに保存可能な形式(シリアライズ形式)に変換するバッキング・マップ実装です。この実装には、シリアライズ形式のデータを保存するcom.tangosol.io.BinaryStore
オブジェクトが別に必要になります。通常、これは組込みのLHディスク・ストア実装ですが、シリアライズ・マップではBinaryStore
の任意のカスタム実装がサポートされます(シリアライズ・マップのデフォルト実装にはcom.tangosol.net.cache.SerializationMap
を使用します)。
シリアライズ・キャッシュ: LRUエビクション・ポリシーをサポートするSerializationMap
の拡張機能です。ディスク・ファイルのサイズ制限などに使用できます (シリアライズ・キャッシュのデフォルト実装にはcom.tangosol.net.cache.SerializationCache
を使用します)。
オーバーフロー・マップ: オーバーフロー・マップは実際には記憶域を提供しませんが、2つのローカル記憶域の実装を結合し、最初の記憶域がいっぱいになると、オーバーフローを行って次の記憶域にデータを保存することから、この項で紹介しています (OverflowMap
のデフォルト実装にはcom.tangosol.net.cache.OverflowMap
を使用します)。
バッキング・マップに対して実行される操作にはいくつかのタイプがあります。
アプリケーションの使用によって必然的に発生するアクセスおよび更新操作。たとえば、NamedCache.get()
コールでは対応するバッキング・マップに対するMap.get()
コールが発生します。また、NamedCache.invoke()
コールではMap.get()
とそれに続くMap.put()
が発生する場合があり、NamedCache.keySet(filter)
コールではMap.entrySet().iterator()
ループが発生する場合があります。
時間ベースの有効期限またはサイズ・ベースのエビクションによって発生する削除操作。たとえば、クライアント層からのNamedCache.get()
コールまたはNamedCache.size()
コールでは、エントリの有効期限切れによるMap.remove()
コールが発生する場合があります。また、NamedCache.put()
コールでは、バッキング・マップの合計データ量が構成済の高水位標値に達した場合に、複数のMap.remove()
コールが(複数のキーに対して)発生する場合があります。
CacheStore.load()
操作によって発生する挿入操作(リードスルー機能またはリードアヘッド機能が構成されたバッキング・マップの場合)
パーティション分散によって発生する統合アクセスおよび更新(クラスタ・ノードのフェイルオーバーまたはフェイルバックから発生する場合もあります)。この場合は、アプリケーション層のコールがなくても、バッキング・マップの多数のエントリが挿入または削除されることがあります。
バッキング・マップでは、実際の実装方法に応じて、次のいずれかの方法でキャッシュ・データが格納されます。
ヒープ上メモリー
ヒープ外メモリー
ディスク(メモリーマップ・ファイルまたはインプロセスDB)
上述のいずれかの組合せ
データをメモリーに格納することで、アクセスおよび更新の待機時間が大幅に短縮されます。また、これは最も一般的に使用される方法でもあります。
たいていの場合、アプリケーションでは、データ・グリッドに配置されるデータの合計量が事前設定されたメモリー量を超えないようにする必要があります。これは、アプリケーション層ロジックによって直接制御することも、サイズ・ベースまたは有効期限ベースのエビクションによって自動的に制御することもできます。その結果、当然のことながら、Coherenceのキャッシュに保持されるデータの合計量は、対応するすべてのバッキング・マップ(対応するパーティション・キャッシュ・サービスを記憶域有効モードで実行するクラスタ・ノードごとに1つ)のデータの合計量と等しくなります。
次のキャッシュ構成の抜粋について検討してみましょう。
<backing-map-scheme> <local-scheme/> </backing-map-scheme>
このバッキング・マップはcom.tangosol.net.cache.LocalCache
のインスタンスであり、事前設定されたサイズの制約がなく、明示的に制御する必要があります。制御できない場合は、JVMがメモリー不足になります。
<backing-map-scheme> <local-scheme> <high-units>100m</high-units> <unit-calculator>BINARY</unit-calculator> <eviction-policy>LRU</eviction-policy> </local-scheme> </backing-map-scheme>
このバッキング・マップもcom.tangosol.net.cache.LocalCache
ですが、100MBの容量制限があります。このバッキング・マップで保持されるデータの合計量が高水位標を超えると、バッキング・マップから一部のエントリが削除され、データの量が低水位標値(<low-units>
構成要素、デフォルトでは<high-units>
の75%)まで減少します。削除されるエントリの選択方法は、LRU(最低使用頻度)エビクション・ポリシーに従います。その他のオプションには、LFU(最低アクセス頻度)および混合(LRUとLFUの組合せ)があります。<high-units>
の値は2GBに制限されます。この制限を解除するため(ただし下位互換性は保持)、Coherenceでは<unit-factor>
要素が使用されます。たとえば、<high-units>
値が8192
で<unit-factor>
が1048576
の場合、高水位標値は8GB
になります。
<backing-map-scheme> <local-scheme> <expiry-delay>1h</expiry-delay> </local-scheme> </backing-map-scheme>
このバッキング・マップは、未更新の状態のまま1時間を超えたエントリを自動的に削除します。ただし、これは「安易な」削除方法であり、最終更新から1時間以上経過していればいつでもエントリが削除される可能性があります。保証されるのは、1時間を超過したエントリがコール元に返されないことのみです。
<backing-map-scheme> <external-scheme> <high-units>100</high-units> <unit-calculator>BINARY</unit-calculator> <unit-factor>1048576</unit-factor> <nio-memory-manager> <initial-size>1MB</initial-size> <maximum-size>100MB</maximum-size> </nio-memory-manager> </external-scheme> </backing-map-scheme>
このバッキング・マップは、com.tangosol.net.cache.SerializationCache
のインスタンスであり、拡張(nio)メモリーに値を格納しますが、100MB(100*1048576)の容量制限があります。このキャッシュのバックアップ記憶域は、off-heap
(またはfile-mapped
)で構成します。
<backup-storage> <type>off-heap</type> <initial-size>1MB</initial-size> <maximum-size>100MB</maximum-size> </backup-storage>
Coherence 3.5より前は、対応するノードが所有するすべてのパーティションのエントリがバッキング・マップに格納されていました (パーティション送信時に、クライアントから見て一時的に所有者の存在しない「未完了」エントリも保持されることがありました)。
図12-2は、従来のバッキング・マップ実装の概念図です。
Coherence 3.5では、パーティション・バッキング・マップの概念が導入されました。これは、基本的には実際のマップ実装の多重化であり、それぞれのマップには同じパーティションに属するエントリのみが格納されるようになりました。
図12-3は、パーティション・バッキング・マップ実装の概念図です。
パーティション・バッキング・マップを構成するには、<partitioned>
要素を、値をtrue
に設定して追加します。例:
<backing-map-scheme> <partitioned>true</partitioned> <external-scheme> <high-units>8192</high-units> <unit-calculator>BINARY</unit-calculator> <unit-factor>1048576</unit-factor> <nio-memory-manager> <initial-size>1MB</initial-size> <maximum-size>50MB</maximum-size> </nio-memory-manager> </external-scheme> </backing-map-scheme>
このバッキング・マップはcom.tangosol.net.partition.PartitionSplittingBackingMap
のインスタンスであり、マップを保持する個別のパーティションであるcom.tangosol.net.cache.SerializationCache
のインスタンスから構成され、各パーティションの拡張(nio)メモリーに値が格納されます。nioバッファにはそれぞれ50MBの制限がありますが、バッキング・マップ全体の容量制限は8GB(8192*1048576)です。この場合も、このキャッシュのバックアップ記憶域はoff-heap
またはfile-mapped
で構成する必要があります。