この章では、データ・アフィニティの使用方法と、デフォルトのパーティション設定の変更方法について説明します。この説明は、分散キャッシュに固有のものです。
この章には次の項が含まれます:
この項には次のトピックが含まれます:
データ・アフィニティは、関連するキャッシュ・エントリ・グループが単一のキャッシュ・パーティションに含まれることを保証する概念を表します。これにより、フォルト・トレランスを犠牲にすることなく、すべての関連データが単一のプライマリ・キャッシュ・ノードで管理されます。
アフィニティは、(同じキャッシュ・サービスで管理されている通常のケースでは)複数のキャッシュにまたがります。たとえば、Order-LineItemのようなマスター/ディテール・パターンでは、Order
オブジェクトが、関連付けられているLineItem
オブジェクトのコレクション全体と共存する場合があります。
データ・アフィニティを使用する利点は2つあります。まず、一連の関連項目に対する問合せおよびトランザクションを、単一のキャッシュ・ノードのみで管理できます。また、すべての並行操作はローカルで管理可能であり、クラスタ化された同期処理は不要です。
アフィニティにより、キャッシュ問合せ、InvocableMap
の操作、およびgetAll
、putAll
、removeAll
などのメソッドを含むCoherenceのいくつかの標準的な操作を効率的に実行できます。
注意: データ・アフィニティは、値ではなくエントリ・キーに関して指定されます。その結果、対応付け情報がキー・クラスに存在している必要があります。同様に、対応付けロジックは、値クラスではなくキー・クラスに適用されます。 |
アフィニティは、パーティション・キーとの関係で指定されます。前述のOrder
-LineItem
の例では、Order
オブジェクトが正常にパーティション化され、LineItem
オブジェクトは適切なOrder
オブジェクトと関連付けられます。
この関連付けは実際の親キーに対して直接実行する必要はなく、親キーの機能マッピングになるだけで十分です。親キーの単一フィールド(一意でない場合でも可能)、または親キーの整数ハッシュとなる場合もあります。重要なのは、すべての子キーで同じ関連キーが返されることだけです。関連キーが実際のキーであるかどうかは重要ではありません(このキーは、単なるグループID)。これにより、親キーの情報を含まない子キー・クラスのサイズの影響を最小限に抑えることができます(導出データであるため、データ・サイズを明示的に決定できるほか、キー動作への影響もありません)。対応付けを汎用化しすぎると(同じグループIDに関連付けられたキーが多すぎる場合)、均一に分散されないことがあります(親キーに関係なく、すべての子キーが同じ対応付けキーを返した場合、子キーはすべて単一パーティションに割り当てられ、クラスタ全体には分散されない)。
一連のキャッシュ・エントリが共存していることを確認するには、2つの方法があります。対応付けが、値ではなくキャッシュ・キーに基づいていることを確認します(そうでない場合、キャッシュ・エントリを更新するとパーティションが変更される可能性がある)。また、Order
が子LineItems
と同じ場所にある場合、Coherenceは現在、複数のキャッシュにまたがる複合操作(単一の呼び出しリクエストcom.tangosol.util.InvocableMap.EntryProcessor
内でのOrder
および
LineItemsのコレクションの更新など)をサポートしていないことに注意してください。
アプリケーション定義のキーでは、キャッシュ・キーのクラスは次のようにcom.tangosol.net.cache.KeyAssociation
を実装できます。
アプリケーションでは、カスタムのKeyAssociator
も指定できます。
例30-2 カスタムのKeyAssociator
import com.tangosol.net.partition.KeyAssociator; public class LineItemAssociator implements KeyAssociator { public Object getAssociatedKey(Object oKey) { if (oKey instanceof LineItemId) { return ((LineItemId) oKey).getOrderId(); } else if (oKey instanceof OrderId) { return oKey; } else { return null; } } public void init(PartitionedService service) { } }
キー・アソシエータは、NamedCache
に関して、そのキャッシュを定義した<distributed-scheme>
要素で構成されます。
キー・アソシエーションは、クラスタ上と拡張クライアント上のいずれでも実装できます。拡張クライアントを使用する場合、最適な方法はそのクライアント上でキー・アソシエーションを実装することです。これにより、キーはクラスタに送信される前に処理されて最適なパフォーマンスが得られます。キー・アソシエーションは、デフォルトではクライアント上で処理されます。クラスタ上でのキー・アソシエーションに依存している既存のクライアント実装で、クラスタ上でキー・クラスが処理されるように強制するには、defer-key-association-check
パラメータを設定する必要があります。
キー・アソシエーション処理をExtendクライアントによってではなくクラスタ側で実行するには、クライアント側キャッシュの構成で<remote-cache-scheme>
要素の<defer-key-association-check>
要素をtrue
に設定します。例:
<remote-cache-scheme> ... <defer-key-association-check>true</defer-key-association-check> </remote-cache-scheme>
注意: パラメータがtrue に設定されている場合、キー・クラス実装は、キー・アソシエーションを使用していない場合でもクラスタ上に存在する必要があります。 |
.NETおよびC++クライアントでのキー・アソシエーションの遅延に関する詳細は、それぞれ、『Oracle Coherenceリモート・クライアントの開発』(.NET
およびC++
)を参照してください。
例30-4は、アフィニティを使用してより効率的な問合せ(NamedCache.entrySet(Filter)
)およびキャッシュ・アクセス(NamedCache.getAll(Collection)
)を作成する方法を示しています。
例30-4 アフィニティを使用した効率的な問合せの作成
OrderId orderId = new OrderId(1234); // this Filter is applied to all LineItem objects to fetch those // for which getOrderId() returns the specified order identifier // "select * from LineItem where OrderId = :orderId"Filter filterEq = new EqualsFilter("getOrderId", orderId); // this Filter directs the query to the cluster node that currently owns // the Order object with the given identifier Filter filterAsc = new KeyAssociatedFilter(filterEq, orderId); // run the optimized query to get the ChildKey objects Set setLineItemKeys = cacheLineItems.keySet(filterAsc); // get all the Child objects immediately Set setLineItems = cacheLineItems.getAll(setLineItemKeys); // Or remove all immediately cacheLineItems.keySet().removeAll(setLineItemKeys);
分散キャッシュ・サービスのデフォルト・パーティション数は257パーティションです。分散キャッシュ・サービスをホストするクラスタ内のキャッシュ・サーバーはそれぞれ均等な数のパーティションを管理します。たとえば、4台のキャッシュ・サーバーからなるクラスタ内の各キャッシュ・サーバーは、64個のパーティションを管理します。デフォルト・パーティション数は、通常、最大16台のキャッシュ・サーバーを含むクラスタで許容されます。ただし、最適なパフォーマンスを確保するには、大きいクラスタほど多くのパーティションが必要です。
分散キャッシュ・サービスのパーティション数を変更するには、キャッシュ構成ファイルを編集し、サービスに使用するパーティション数を含む<partition-count>
要素を<distributed-scheme>
要素内に追加します。例:
<distributed-scheme> <scheme-name>distributed</scheme-name> <service-name>DistributedCache</service-name> <partition-count>1181</partition-count> ... </distributed-scheme>
パーティション数の決定
パーティション数を選択するための正確な計算式はありません。理想的なパーティション数は、各クラスタ・メンバー上のパーティション数と、各パーティションによって保持されるデータ量とのバランスが取れているものです。パーティション数を選択する際は次のガイドラインを使用し、常にテストを実行してそのパーティション数でパフォーマンスが低下しないことを確認します。
パーティション数は常に素数にする必要があります。素数のリストは、http://primes.utm.edu/lists/
にあります。
パーティション数は十分な大きさにして、各メンバーによって管理されるパーティション数が少なすぎることのないバランスのとれた分散がサポートされるようにする必要があります。たとえば、各メンバー上のパーティションが2つのみになるパーティション数では制約的すぎます。
パーティション数は、転送オーバーヘッドおよび多数のパーティション転送(転送単位は1パーティション)の記録処理にネットワーク帯域幅が浪費されるほど大きくしないでください。たとえば、数千のパーティションを新しいキャッシュ・サーバー・メンバーに転送すると、大量のネットワーク・リソースが必要になり、特に起動時にクラスタ・パフォーマンスが低下することがあります。
1つのパーティションによって管理されるデータ量が大きすぎないようにしてください(1つのパーティションが管理するデータが多くなるほどパーティションのプロモーションおよび転送のコストが高くなります)。1つのパーティションによって管理されるデータ量は、キャッシュ・サーバーで使用可能なメモリー量によってのみ制限されます。通常は、パーティションの制限が50MBあれば、良好なパフォーマンスが保証されます。大規模なクラスタでは、パーティションの制限に50MBから100MB (速度が10GbE以上でさらに大きな容量)が使用されることもあります。さらに大きな制限を使用することもできますが、転送の待機時間がわずかに増加することと、オーバーヘッド領域が増加して大きなヒープが必要になることを理解しておいてください。
例として、4GBのヒープで構成され、索引を含まないプライマリ・データを約1.3GB格納する(ヒープの2/3をバックアップおよびスクラッチ領域のために残しておく)キャッシュ・サーバーを考えてみましょう。決定したパーティションの制限が控え目な25MBである場合、1台のキャッシュ・サーバーで問題なく53個のパーティションを使用できます(1365MB/25MBが切り捨てられてその前の素数になります)。したがって、20台のキャッシュ・サーバーを含む1つのクラスタは問題なく1051個のパーティションを使用でき(53*20が切り捨てられてその前の素数になる)、約25GBのプライマリ・データを格納します。100台のキャッシュ・サーバーからなる1つのクラスタは問題なく5297個のパーティションを使用でき、約129GBのプライマリ・データを格納できます。
パーティション分散では、パーティションがどのように、記憶域が有効なクラスタ・メンバーに割り当てられるかを定義します。使用可能な分散スタイルには次の2つがあります。
自律型分散 - この分散方法では、記憶域が有効な各サービス・メンバーは、サービスのバランスを取るために、使用可能なパーティションについて各自のバランスの取れた割当てを計算し、分散をリクエストします。
集中管理型分散 – この分散戦略では、集中パーティション割当て戦略を使用して、記憶域が有効な各メンバーによってグローバルな分散決定が行われるようにします。集中管理型の分散は、より表現力のある分散アルゴリズムを使用することを可能にし、サービスに関するより完全でグローバルなビューを使用します。
カスタム集中管理型分散戦略は、com.tangosol.net.partition.PartitionAssignmentStrategy
インタフェースを実装することで作成できます。
使用可能な事前定義済パーティション割当て戦略は次のとおりです。
legacy
- (非推奨)レガシー割当て戦略では、パーティション分散は各クラスタ・メンバーで個々に管理されます。レガシー・パーティション割当て戦略は、自律型分散戦略です。
simple
- (デフォルト)単純な割当て戦略は、マシンの安全性を確保しながらパーティション分散のバランスを取ることを試みる集中管理型分散戦略であり、レガシー戦略よりも決定論的で効率的です。
mirror:<
service-name
>
– ミラー割当て戦略は、サービスのパーティションを、指定されたサービスのパーティションと共存させることを試みる集中管理型分散戦略です。この戦略は、キーを関連付けられたクロスサービス・キャッシュ・アクセスがメンバーに対してローカルのままになる可能性を高めるために使用されます。
custom - com.tangosol.net.partition.PartitionAssignmentStrategy
インタフェースを実装するクラス。
特定のパーティション・キャッシュ・サービスに対してパーティション割当て戦略を構成するには、分散キャッシュ定義内に<partition-assignment-strategy>
要素を追加します。
<distributed-scheme> ... <partition-assignment-strategy>mirror:<MyService> </partition-assignment-strategy> ... </distributed-scheme>
分散キャッシュ・サービス・タイプのすべてのインスタンスに対してパーティション割当て戦略を構成するには、オペレーション・オーバーライド・ファイル内のパーティション・キャッシュ・サービスのpartition-assignment-strategy
初期化パラメータをオーバーライドします。例:
<?xml version='1.0'?> <coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config" xsi:schemaLocation="http://xmlns.oracle.com/coherence/ coherence-operational-config coherence-operational-config.xsd"> <cluster-config> <services> <service id="3"> <init-params> <init-param id="21"> <param-name>partition-assignment-strategy</param-name> <param-value>mirror:<MyService></param-value> </init-param> </init-params> </service> </services> </cluster-config> </coherence>
カスタムのパーティション割当て戦略を指定するには、<partition-assignment-strategy>
要素内に<instance>
サブ要素を含めて、com.tangosol.net.partition.PartitionAssignmentStrategy
インタフェースを実装する完全修飾クラス名を指定します。カスタム・クラスは、com.tangosol.net.partition.SimpleAssignmentStrategy
クラスを拡張することもできます。<instance>要素の使用の詳細は、「instance」
を参照してください。次の例では、MyPAStrategy
クラスで実装されるパーティション割当て戦略を有効にします。
<distributed-scheme> ... <partition-assignment-strategy> <instance> <class-name>package.MyPAStrategy</class-name> </instance> </partition-assignment-strategy> ... </distributed-scheme>
代替案として、<instance>
要素では、PartitionAssignmentStrategy
インスタンスを作成するためのファクトリ・クラスを使用する<class-factory-name>
要素、およびオブジェクトのインスタンス化を実行するファクトリ・クラス上で静的なファクトリ・メソッドを指定する<method-name>
要素の使用がサポートされています。次の例では、MyPAStrategyFactory
クラスでgetStrategy
メソッドを使用して、戦略のインスタンスを取得します。
<distributed-scheme> ... <partition-assignment-strategy> <instance> <class-factory-name>package.MyPAStrategyFactory</class-factory-name> <method-name>getStrategy</method-name> </instance> </partition-assignment-strategy> ... </distributed-scheme>
実装に必要な初期化パラメータはすべて、<init-params>
要素を使用して指定できます。次の例では、iMaxTime
パラメータが2000
に設定されます。
<distributed-scheme> ... <partition-assignment-strategy> <instance> <class-name>package.MyPAStrategy</class-name> <init-params> <init-param> <param-name>iMaxTime</param-name> <param-value>2000</param-value> </init-param> </init-params> </instance> </partition-assignment-strategy> ... </distributed-scheme>