この章では、アプリケーション・サーバー環境でスケーラビリティを保証するためにOracle TopLinkアプリケーションを構成する手順を説明します。この手順は、すべてのアプリケーション・サーバー・クラスタに適用できる汎用的なものですが、Oracle WebLogic ServerおよびOracle GlassFish Serverに対応した追加のコンテンツも用意されています。必要に応じて、ベンダーのドキュメントを参照してください。
この章の内容は次のとおりです。
ユース・ケース
顧客の要求に応えるためにアプリケーションを拡張する必要があります。
解決方法
この実装は、キャッシュの構成、キャッシュ・コーディネーションの構成、データのパーティション化を使用して実現できます。
コンポーネント
TopLink 12c (12.1.2.0.0)以上。
注意: TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。 |
クラスタをサポートするアプリケーション・サーバー。
対応するすべてのJDBCデータベース。
例
サンプルへのリンクは、10.3項「その他の参考資料」を参照してください。
アプリケーション・サーバー・クラスタにデプロイされたEclipseLinkアプリケーションは、クラスタのスケーラビリティ、負荷分散およびフェイルオーバーのメリットを受けることができます。これらの機能は、EclipseLinkアプリケーションの可用性を高め、アプリケーションの需要拡大に伴ってスケーリングできます。EclipseLinkのアプリケーションは、アプリケーション・サーバー・クラスタへも、スタンドアロンのサーバー環境と同様にデプロイできます。ただし、アプリケーション・サーバー・クラスタの場合には、キャッシュの一貫性を確保するために、その他に計画や構成を実行する必要があります。
EclipseLinkでは、オブジェクトおよびそのリレーションシップのデータベース・アクセスを回避する共有(L2)オブジェクト・キャッシュが利用されます。このキャッシュはデフォルトで有効になり、アプリケーションのパフォーマンスが向上します。アプリケーション・サーバー・クラスタでキャッシングを使用すると、1つのサーバーで行われた変更が、他のサーバーでキャッシュされているオブジェクトに反映されないために、整合性の問題(失効データなど)が発生する場合があります。キャッシュの整合性が問題になるのは、頻繁に更新されるオブジェクトのみです。読取り専用のオブジェクトは、キャッシュの整合性の影響を受けません。キャッシュの詳細は、次を参照してください。
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching/Caching_Overview
キャッシュの整合性に対処するには、次のように様々な方法があります。
キャッシュ・コーディネーションを使用します。キャッシュ・コーディネーションは、クラスタ内のサーバー間で変更をブロードキャストして、変更されたオブジェクトの更新または無効化を行う機能です。
分散キャッシングを使用します。TopLink Gridとは、TopLinkとOracle Coherenceを統合した、分散環境で運用した場合に発生するキャッシュの整合性の問題の多くに対処するものです。TopLink Gridの詳細は、第19章「TopLink GridでのOracle Coherenceを使用したアプリケーションのスケーリング」を参照してください。
オプティミスティック・ロックを使用します。オプティミスティック・ロックは、無効なオブジェクトへの更新を防ぎ、キャッシュ内でオブジェクトが無効化されるようにトリガーする機能です。
キャッシュをリフレッシュします。キャッシュを更新すると、キャッシュに最新のデータがロードされます。
非常に不安定なエンティティでは共有キャッシュを無効にするか、キャッシュを読取り専用オブジェクトに制限します。
次のタスクでは、EclipseLinkアプリケーションをアプリケーション・サーバー・クラスタでスケーリングするための一般的な手順を説明します。タスクは、アプリケーションのデプロイ前に完了する必要があります。
この項の内容は次のとおりです。
このタスクには、アプリケーション・サーバーのクラスタにアプリケーションがデプロイされた場合に、アプリケーションが失効データを使用する可能性を少なくする様々な構成オプションが含まれています。キャッシュ・コーディネーション・オプションは、クラスタ化されたアプリケーション用に特に設計されていますが、すべてのオプションを評価し、(適用可能な場合は)一緒に使用して、アプリケーションのパフォーマンスが最高になるようなソリューションを作成します。キャッシュを適切に構成すれば、キャッシュ・コーディネーションを使用する必要がなくなる場合もあります。これらのオプションの詳細は、次を参照してください。
http://wiki.eclipse.org/Introduction_to_Cache_%28ELUG%29#Handling_Stale_Data
次の構成オプションを利用できます。
注意: TopLinkでCoherenceをL2キャッシュとして使用できるようにするTopLinkとCoherenceの統合が提供されています。TopLink Gridの詳細は、第19章「TopLink GridでのOracle Coherenceを使用したアプリケーションのスケーリング」を参照してください。 |
非常に不安定なエンティティまたは必要に応じてすべてのエンティティで共有キャッシュを無効にします。すべてのオブジェクトの共有キャッシュを無効にするには、persistence.xml
ファイルの<shared-cache-mode>
要素を使用します。次に例を示します。
<shared-cache-mode>NONE</shared-cache-mode>
デフォルトでは、DISABLE_SELECTIVE
が構成されており、エンティティごとにキャッシュを無効にできます。共有キャッシュを選択的に有効または無効にするには、エンティティを定義する際に、@Cache
注釈のshared
属性を使用します。次に例を示します。
@Entity @Cache(shared=false) public class Employee { }
アプリケーションが現在のデータの使用を確実にするために、キャッシュをリフレッシュするとデータベースからキャッシュがリロードされます。キャッシュは様々な方法でリフレッシュできます。
@Cache
注釈には、データベースに対するすべての問合せで強制的にキャッシュをリフレッシュさせるalwaysRefresh
属性とrefreshOnlyIfNewer
属性が用意されています。キャッシュは、データベース内のオプティミスティック・ロック値がキャッシュ内のものよりも実際に新しい場合にのみリフレッシュされます。
@Entity @Cache( alwaysRefresh=true, refreshOnlyIfNewer=true) public class Employee { }
javax.persistence.Cache
インタフェースには、キャッシュが最新でない場合に失効オブジェクトを削除するメソッドが含まれています。
evictAll
メソッドは、キャッシュ内のすべてのオブジェクトを無効にします。
em.getEntityManagerFactory().getCache().evictAll();
evict
メソッドは、特定のクラスを無効にします。
em.getEntityManagerFactory().getCache().evict(MyClass);
これまでに説明したメソッドは受動的で、次回にキャッシュにアクセスしたときにのみオブジェクトがリフレッシュされます。オブジェクトを能動的にリフレッシュするには、EntityManager.
refresh
メソッドを使用します。このメソッドは1回に1つのオブジェクトをリフレッシュします。
キャッシュをリフレッシュする問合せをトリガーする、問合せのヒントを設定するsetHint
メソッドを設定することも可能です。次に例を示します。
Query query = em.createQuery("Select e from Employee e"); query.setHint("javax.persistence.cache.storeMode", "REFRESH");
最後にネイティブAPIのメソッドも使用できます。詳細は、『Oracle TopLink Java APIリファレンス』のClassDescriptor
に関する項を参照してください。
キャッシュ有効期限を設定した場合、指定時間が経過すると、キャッシュされたオブジェクト・インスタンスが無効になります。そのオブジェクトを使用しようとすると、最新バージョンのオブジェクトがデータ・ソースからリロードされます。有効期限は、アプリケーションが確実に最新データを使用するようにするのに便利です。有効期限を設定するには、様々な方法があります。
@Cache
注釈には、特定の時間が経つとキャッシュ・インスタンスを削除するexpiry
およびexpiryTimeOfDay
属性が用意されています。expiry
属性は、ミリ秒単位で入力します。値を指定しない場合のデフォルト値は-1
で、有効期限が無効になっていることを示します。expiryTimeOfDay
属性は、org.eclipse.persistence.annotations.TimeOfDay
インタフェースのインスタンスです。次の例では、5分後にオブジェクトが期限切れになるように設定しています。
@Entity @Cache(expiry=300000) public class Employee { }
オプティミスティック・ロックでは、あるユーザーが別のユーザーの作業を上書きできないようにします。ロックは、複数のサーバーまたは複数のアプリケーションが同じデータにアクセスする場合に重要で、単一サーバーとマルチサーバーの両方の環境に関係があります。マルチサーバー環境においては、アプリケーションがキャッシュ・リフレッシュやキャッシュ・コーディネーションを使用している場合であっても、やはりロックは必要です。オプティミスティック・ロックを設定するには、様々な方法があります。
標準のJPA @Version
の注釈は、単一値の値およびタイムスタンプ・ベースのロックで使用されます。ただし、高度なロッキング機能には、@OptimisticLocking
注釈を使用します。@OptimisticLocking
注釈には、エンティティを更新または削除する際に使用するオプティミスティック・ロックのタイプを指定します。オプティミスティック・ロックは、@Entity
または@MappedSuperclass
注釈でサポートされています。次のポリシーをtype
属性内に設定して利用できます。
ALL_COLUMNS
: このポリシーでは、更新または削除操作を実行するときに、WHERE
句で表のすべてのフィールドを比較します。
CHANGED_COLUMNS
: このポリシーでは、更新操作の実行時に、WHERE
句で変更されたフィールドのみを比較します。削除操作では、主キーのみが比較されます。
SELECTED_COLUMNS
: このポリシーでは、更新または削除操作を実行するときに、WHERE
句で選択したフィールドを比較します。指定したフィールドはマップされている必要があり、主キーではない必要があります。
VERSION_COLUMN
: (デフォルト)このポリシーでは、単一のバージョン番号をオプティミスティック・ロックに使用することを許可します。バージョン・フィールドはマップされている必要があり、主キーではない必要があります。親オブジェクトが私有する子オブジェクトのバージョン・フィールドが変更された場合に、その親オブジェクトのバージョン・フィールドが強制的に自動更新されるようにするには、cascaded
メソッドをtrue
に設定します。デフォルトでは、このメソッドはfalse
に設定されます。
キャッシュ・コーディネーションは、分散セッション間で変更を同期します。すべてのアプリケーションでデータの整合性を維持するのが困難なアプリケーション・サーバー・クラスタでは、キャッシュ・コーディネーションが最も有効です。さらに、1つの環境内のサーバー数が増えるにつれて、キャッシュの整合性を保つのはますます難しくなります。
キャッシュ・コーディネーションは、クラスタ内のセッション(EntityManagerFactory
または永続性ユニット)間のトランザクション・オブジェクトの変更通知をブロードキャストすることにより動作します。アプリケーションが読取り中心で、複数の分散セッションで運用される同一アプリケーションによって変更が実行される場合に、キャッシュ・コーディネーションは最も有効です。
キャッシュ・コーディネーションを使用すると、失効データが大幅に減少しますが、遅延のために失効データが発生する可能性を完全になくすことはできません。さらに、キャッシュ・コーディネーションにより、分散アーキテクチャで発生するオプティミスティック・ロック例外の数は減少し、アプリケーションで失敗するトランザクションや繰り返されるトランザクションの数も減少します。とはいえ、キャッシュ・コーディネーションを行っても、効果的なロック・ポリシーが不要になることはありません。現在のデータを確実に使用するには、オプティミスティック・ロックまたはペシミスティック・ロックとともにキャッシュ・コーディネーションを使用しますが、オプティミスティック・ロックの使用の方をお薦めします。
キャッシュ・コーディネーションはRemote Method Invocation (RMI)およびJava Message Service (JMS)プロトコル上でサポートされており、persistence.xml
ファイルの永続性プロパティを使用して宣言的に構成することも、キャッシュ・コーディネーションのAPIを使用して構成することもできます。永続性プロパティに一致するシステム・プロパティも使用できます。
キャッシュ・コーディネーションの詳細は、次を参照してください。
『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』
キャッシュ同期では、オブジェクトの変更通知がセッション・メンバー間にブロードキャストされる方法を決定します。使用できる同期オプションは次のとおりです。
SEND_OBJECT_CHANGES
: (デフォルト)このオプションでは、変更に関するデータを含む、変更されたオブジェクトのリストがブロードキャストされます。このデータは、受信キャッシュにマージされます。
INVALIDATE_CHANGED_OBJECTS
: このオプションでは、変更されたオブジェクトのIDリストがブロードキャストされます。受信キャッシュでは、データを変更するのではなく、オブジェクトが無効にされます。このオプションは、他のクラスタ・メンバーに対しデータを送信したり処理を実行するには最も軽量です。
SEND_NEW_OBJECTS_WITH_CHANGES
: このオプションは、トランザクションで新規作成されたオブジェクトも含まれる点以外はSEND_OBJECT_CHANGES
オプションと同じです。
NONE
: このオプションでは、キャッシュ・コーディネーションは行われません。
@cache
注釈のcoordinationType
属性は、同期を指定するために使用します。次に例を示します。
@Entity @Cache(CacheCoordinationType.SEND_NEW_OBJECTS_CHANGES) public class Employee { }
ClassDescriptor.setCacheSynchronizationType
ネイティブAPIメソッドも、同期を指定するために使用できます。詳細は、『Oracle TopLink Java APIリファレンス』のClassDescriptor
に関する項を参照してください。
次の例は、persistence.xml
ファイルでキャッシュ・コーディネーションを構成する方法を示しており、通知のブロードキャストにJMSを使用しています。JMSでは、JMSトピック、JNDI名およびトピック接続ファクトリのJNDI名を指定します。JMSトピックでは、JTAを有効にせず、永続性メッセージを指定しないでください。
<property name="eclipselink.cache.coordination.protocol" value="jms" /> <property name="eclipselink.cache.coordination.jms.topic" value="jms/EmployeeTopic" /> <property name="eclipselink.cache.coordination.jms.factory" value="jms/EmployeeTopicConnectionFactory" />
クラスタで実行されるアプリケーションでは、リソースを探して使用するにはトピックで十分なので、URLは通常不要です。クラスタ外部で実行されるアプリケーションの場合は、URLが必要です。WebLogicサーバー・クラスタのURLの例を次に示します。
<property name="eclipselink.cache.coordination.jms.host" value="t3://myserver:7001/" />
必要な場合は、サーバーにアクセスするために必要なユーザー名とパスワードも設定できます。次に例を示します。
<property name="eclipselink.cache.coordination.jndi.user" value="user" />
<property name="eclipselink.cache.coordination.jndi.password" value="password" />
次の例は、persistence.xml
ファイルでキャッシュ・コーディネーションを構成する方法を示し、通知のブロードキャストにRMIを使用しています。
<property name="eclipselink.cache.coordination.protocol" value="rmi" />
クラスタで実行されるアプリケーションでは、JNDIがレプリケートされてサーバーが相互を参照できるので、URLは通常不要です。アプリケーションがクラスタ外部で実行される場合またはJNDIがレプリケートされない場合は、各サーバーでURLを指定する必要があります。これは、persistence.xml
ファイルを使用して行えますが、各サーバーに対して別のpersistence.xml
ファイル(たとえばJARまたはEAR)が必要になり、通常は望ましくありません。2番目のオプションとしては、キャッシュ・コーディネーションAPIを使用して、URLをプログラムで設定します。詳細は、「キャッシュ・コーディネーションAPIを使用したキャッシュ・コーディネーションの構成」を参照してください。最後のオプションは、各アプリケーション・サーバーのシステム・プロパティとしてURLを設定する方法です。次の例では、システム・プロパティを使用してWebLogicサーバー・クラスタのURLを設定しています。
-Declipselink.cache.coordination.jms.host=t3://myserver:7001/
必要な場合は、サーバーにアクセスするために必要なユーザー名とパスワードも、次のように設定できます。
<property name="eclipselink.cache.coordination.jndi.user" value="user" /><property name="eclipselink.cache.coordination.jndi.password" value="password" />
RMIキャッシュ・コーディネーションでは、非同期または同期のブロードキャスト通知を使用できます(デフォルトでは非同期です)。同期ブロードキャストでは、リクエストが返される前に、すべてのサーバーが確実に更新されます。次の例では、同期ブロードキャストを構成しています。
<property name="eclipselink.cache.coordination.propagate-asynchronously" value="false" />
同じサーバーまたはネットワーク上の複数のアプリケーションがキャッシュ・コーディネーションを使用する場合は、アプリケーションごとに別のチャネルを使用できます。次に例を示します。
<property name="eclipselink.cache.coordination.channel" value="EmployeeChannel" />
最後に、必要に応じて、サーバーが相互に検索できるようにするデフォルトのRMIマルチキャスト・ソケット・アドレスを変更します。次の例では、マルチキャスト設定を明示的に構成しています。
<property name="eclipselink.cache.coordination.rmi.announcement-delay" value="1000" /> <property name="eclipselink.cache.coordination.rmi.multicast-group" value="239.192.0.0" /> <property name="eclipselink.cache.coordination.rmi.multicast-group.port" value="3121" /> <property name="eclipselink.cache.coordination.packet-time-to-live" value="2" />
RMIのキャッシュ・コーディネーションとJMSのキャッシュ・コーディネーションの両方ともOracle WebLogic Serverで動作します。WebLogicクラスタが使用される場合、JNDIがクラスタ・サーバー間でレプリケートされるため、cache.coordination.rmi.url
またはcache.coordination.jms.host
オプションは不要です。JMSのキャッシュ・コーディネーションでは、JMSトピックは(Oracle WebLogic 10.3.6以上の)サーバーの1つにのみデプロイする必要があります。JMSメッセージの通信量が多い場合、状況に応じて専用のJMSサーバーを用意することをお薦めします。
WebLogicで他のJMSサービスを使用する場合、他の要件が存在することがあります。
JMSのキャッシュ・コーディネーションはGlassfish Serverで動作します。Glassfishクラスタが使用される場合、JNDIがクラスタ・サーバー間でレプリケートされるため、cache.coordination.jms.host
オプションは不要です。
Glassfishで他のJMSサービスを使用する場合、他の要件が存在することがあります。
RMIのキャッシュ・コーディネーションは、JNDIネーミング・サービス・オプションがGlassfishクラスタで使用されている場合には動作しません。RMIは、eclipselink.cache.coordination.naming-service
オプションがrmi
に設定されている場合に動作します。各サーバーでは、サーバーごとに異なるpersistence.xml
ファイルを用意するか、サーバーのシステム・プロパティとしてURLを設定するか、カスタマイザを使用して独自のeclipselink.cache.coordination.rmi.url
オプションを提供する必要があります。
JMSのキャッシュ・コーディネーションでは、IBM WebSphere上で問題が発生することがあります。JMSへのアクセスを可能にするため、メッセージドリブンBean (MDB)の使用が必要になることがあります。MDBをキャッシュ・コーディネーションとともに使用するには、eclipselink.cache.coordination.protocol
オプションの値をjms-publishing
に設定します。アプリケーションでも、そのEARファイルのキャッシュ・コーディネーション・メッセージを処理するMDBをデプロイする必要があります。
CommandManager
インタフェースを使用して、セッションのキャッシュ・コーディネーションをプログラムで構成します。インタフェースは、DatabaseSession
インタフェースのgetCommandManager
メソッドを使用してアクセスします。
EclipseLink JARファイルが、EclipseLinkアプリケーションがデプロイされているクラスタの各アプリケーション・サーバーのクラスパスに含まれていることを確認して、EclipseLinkを永続性プロバイダとして構成します。TopLinkをWebLogic ServerおよびGlassFish Serverで設定する方法の詳細は、第3章「WebLogic ServerでのTopLinkの使用」および第4章「GlassFish ServerでのTopLinkの使用」をそれぞれ参照してください。
EclipseLinkアプリケーションをホストする各アプリケーション・サーバーを含むアプリケーション・サーバー・クラスタを構成します。
注意: TopLinkはJMSおよびRMIに依存し、アプリケーション・サーバーのクラスタ構成は使用しません。 |
WebLogic Serverのクラスタ化の詳細は、『Oracle WebLogic Serverクラスタの管理』を参照してください。
GlassFish Serverのクラスタ化の詳細は、次を参照してください。
http://download.oracle.com/docs/cd/E18930_01/html/821-2426/index.html
データのパーティション化では、1つ以上のデータベース・マシンにアプリケーションのデータをスケーリングします。データのパーティション化では、同じクラスの別のセットのエンティティ・インスタンスを、別の物理データベースまたはデータベース・クラスタの別のノードにエンティティ・レベルで保存することをサポートしています。標準のデータベースもクラスタ化されたデータベースもサポートされています。データは水平にも垂直にもパーティション化できます。
パーティションは、エンティティ、リレーションシップ、問合せ、永続性ユニットで有効にできます。データのパーティション化を構成するには、@Partitioned
注釈と1つ以上のパーティショニング・ポリシー注釈を使用します。表10-1では、パーティション・ポリシーについて説明します。
表10-1 パーティション・ポリシー
注釈 | 説明 |
---|---|
|
パーティションは、オブジェクトのID、場所、テナントなどのオブジェクトのフィールド値のハッシュからデータベース・クラスタにアクセスします。接続プール/ノード一覧に対してハッシュ索引を作成します。そのハッシュ値を持つオブジェクトに対するすべての書込みまたは読取り要求は、同じサーバーに送信されます。問合せにパラメータとしてハッシュ・フィールドが含まれない場合、すべてのサーバーに送信され結合されるか、セッションのデフォルトの処理が行われます。 |
|
1つの接続プール/ノードに要求を固定します。これによりパーティショニングは垂直方向で行われるようになります。 |
|
パーティションは、オブジェクトのID、場所、テナントなどのオブジェクトのフィールド値を使用しデータベース・クラスタにアクセスします。各サーバーには値の範囲が割り当てられます。その値を持つオブジェクトに対するすべての書込みまたは読取り要求は、同じサーバーに送信されます。問合せにパラメータとしてそのフィールドが含まれない場合、すべてのサーバーに送信され結合されるか、セッションのデフォルトの処理が行われます。 |
|
接続プール/ノードのセットに要求を送信します。このポリシーは、データベース・マシンのクラスタ間でデータをレプリケートするためのものです。変更の問合せのみがレプリケートされます。 |
|
接続プール/ノードのセットにラウンドロビン方式で要求を送信します。このポリシーは、データベース・マシンのクラスタ全体に対して、読取り問合せの負荷を分散するために使用します。これでは、パーティショニングをサポートしないよう、データベースを完全にマシンにレプリケートする必要があります。データは、読取り専用のみであるか、書込みをレプリケートする必要があります。 |
|
問合せをすべての接続プールに送信し、結果を結合します。これは、ManyToManyのパーティションをまたがるリレーションシップなど、パーティショニングが使用されているときに、パーティションをまたぐ問合せやリレーションシップで使用します。 |
|
パーティションは、オブジェクトの場所やテナントなどのオブジェクトのフィールド値を使用しデータベース・クラスタにアクセスします。各値には特定のサーバーが割り当てられます。その値を持つオブジェクトに対するすべての書込みまたは読取り要求は、同じサーバーに送信されます。問合せにパラメータとしてフィールドが含まれない場合、すべてのサーバーに送信され結合されるか、セッションのデフォルトの処理が行われます。 |
|
パーティションは、カスタム・パーティション・ポリシーを使用してデータベース・クラスタにアクセスします。 |
パーティション・ポリシーとは、永続性ユニットでグローバルに命名されたオブジェクトで、複数の識別子または問合せで再利用できます。これにより、特にJPA注釈およびXMLの構成の使い勝手が向上します。
永続性ユニットのプロパティは、読取り、書込み、シーケンスの既存の構成に加え、名前付きの接続プールの追加をサポートしています。接続プールは、参加している各データベースのpersistence.xml
ファイル内に定義します。パーティション・ポリシーは、その特定のアルゴリズムに基づいて適切な接続を選択します。
トランザクションにより複数のパーティションのデータが変更される場合、JTAを使用してデータが2段階でコミットされるようにする必要があります。1つのトランザクションに1つのノードのみが使用されるようEntityManager
の実装で排他接続を構成することも可能です。
次の例では、場所ごとにEmployee
データをパーティション分割します。2つの主要サイトOttawaおよびTorontoは、それぞれ別のデータベースに保存されています。その他のすべての場所は、デフォルトのデータベースに保存されています。プロジェクトはそのIDで範囲がパーティション分割されています。ID値の各範囲は、別のデータベースに保存されます。
@Entity @IdClass(EmployeePK.class) @UnionPartitioning( name="UnionPartitioningAllNodes", replicateWrites=true) @ValuePartitioning( name="ValuePartitioningByLOCATION", partitionColumn=@Column(name="LOCATION"), unionUnpartitionableQueries=true, defaultConnectionPool="default", partitions={ @ValuePartition(connectionPool="node2", value="Ottawa"), @ValuePartition(connectionPool="node3", value="Toronto") }) @Partitioned("ValuePartitioningByLOCATION") public class Employee { @Id @Column(name = "EMP_ID") private Integer id; @Id private String location; ... @ManyToMany(cascade = { PERSIST, MERGE }) @Partitioned("UnionPartitioningAllNodes") private Collection<Project> projects; ... }
従業員とプロジェクトのリレーションシップが、パーティションをまたぐリレーションシップの例です。従業員およびプロジェクトを別のデータベースに保存するために、結合ポリシーが使用され、結合表が各データベースにレプリケートされます。
@Entity @RangePartitioning( name="RangePartitioningByPROJ_ID", partitionColumn=@Column(name="PROJ_ID"), partitionValueType=Integer.class, unionUnpartitionableQueries=true, partitions={ @RangePartition(connectionPool="default", startValue="0", endValue="1000"), @RangePartition(connectionPool="node2", startValue="1000", endValue="2000"), @RangePartition(connectionPool="node3", startValue="2000") }) @Partitioned("RangePartitioningByPROJ_ID") public class Project { @Id @Column(name="PROJ_ID") private Integer id; ... }
一部のデータベースでは、複数のサーバーにデータベースをクラスタリングできます。Oracle Real Application Clusters (RAC)では1つのデータベースを別の複数のサーバー・ノードにスパンできます。Oracle RACでは、データを表およびノードでパーティション化することも可能です。データベース・クラスタを使用すると、クラスタの任意のノードから任意のデータにアクセスできます。ただし、一般的には、ノード間での通信を減らすために、データへのアクセスを特定のノードにパーティション化する方が効率的です。パーティション化を、クラスタ・データベースとともに使用すると、ノード間の通信を減らし、拡張性を向上させることができます。Oracle RACでEclipseLinkを使用する方法の詳細は、24.2.5項「Oracle RACでのEclipseLinkの使用」を参照してください。
データベース・クラスタでデータのパーティション化を使用する際の要件は、次のとおりです。
データベース・クラスタによりすべてのノードがデータを利用できるようになってしまうので、パーティション・ポリシーでは、レプリケーションを有効にしないようにする必要があります。
データベース・クラスタによりすべてのノードの問合せ結果がすべて返されてしまうので、パーティション・ポリシーでは結合を使用しないようにする必要があります。
クラスタの各ノードにDataSource
および接続プールを定義する必要があります。
アプリケーションのデータ・アクセスおよびデータ・パーティション化で、各トランザクションが1つのノードにのみアクセスするよう設計する必要があります。
1つのトランザクションで複数のノードがあったり、2段階でのコミットを避けるは、EntityManager
で排他接続を使用することが推奨されます。
この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。
次のコード例およびJavaDocの参考資料を参照できます。
コード例
『Oracle TopLink Java APIリファレンス』で次のAPIに関する項を参照してください。
org.eclipse.persistence.annotations.OptimisticLocking
org.eclipse.persistence.annotations.Cache
org.eclipse.persistence.annotations.Partitioned
org.eclipse.persistence.descriptors.ClassDescriptor
org.eclipse.persistence.sessions.coordination