この章の内容は次のとおりです。
com.tangosol.net.NamedCache<K, V>
インタフェースは、アプリケーションがキャッシュ・インスタンスを取得して、それとやりとりするために使用する主要インタフェースです。NamedCache
インスタンスへの参照を取得するために、アプリケーションはSession
APIおよびCacheFactory
APIを使用できます。Map
インタフェースで定義されているput
メソッドを使用して実行されます。Map
インタフェースで定義されているget
メソッドを使用して実行されます。Map
インタフェースで定義されているremove
メソッドを使用して実行されます。Map
メソッドの実装をオーバーライドして、これらの操作が分散環境で適切に実行されることを保証します。NamedCache
インタフェースで定義されるclear
またはtruncate
メソッドを使用してクリアできます。CacheFactory.release
メソッドを使用して、指定されたキャッシュのインスタンスに関連付けられているローカル・リソースを解放する必要があります。CacheFactory
クラスを使用して作成されるキャッシュは、CacheFactory.destroy
メソッドを使用して破棄できます。com.tangosol.net.AsyncNameCache<K, V>
インタフェースにより、キャッシュ操作を並列に完了できます。Session
またはCacheFactory
APIのいずれかを使用している場合、厳密に型指定されたNamedCache
インスタンスをリクエストできます。親トピック: データ・グリッド操作の実行
com.tangosol.net.NamedCache<K, V>
インタフェースは、キャッシュ・インスタンスの取得と操作のためにアプリケーションによって使用される主要インタフェースです。NamedCache<K, V>
インタフェースは、他の各種インタフェースを拡張し、Coherence固有のデータ・グリッド操作の実行に使用される追加のキャッシュ機能をそれぞれ提供します。拡張されたインタフェースには、次のものがあります。
java.util.Map<K, V>
- このインタフェースでは、get()
、put()
、remove()
などの基本的なMap
メソッドが提供されます。
com.tangosol.net.cache.CacheMap<K, V>
- このインタフェースでは、キャッシュ内にあるキーの集合を取得(Map
として)する、およびオブジェクトをキャッシュに入れるためのメソッドが提供されます。このインタフェースでは、エントリをキャッシュに入れるときに有効期限の値を追加することもできます。
com.tangosol.util.QueryMap<K, V>
- このインタフェースでは、キャッシュを問い合せるためのメソッドが提供されます。キャッシュ内のデータの問合せを参照してください。
com.tangosol.util.InvocableMap<K, V>
- このインタフェースでは、キャッシュ・データのサーバー側処理のためのメソッドが提供されます。キャッシュ内のデータの処理を参照してください。
com.tangosol.util.ObservableMap<K, V>
- このインタフェースでは、キャッシュ・イベントをリスニングするためのメソッドが提供されます。(マップ・イベントの使用を参照してください)。
com.tangosol.util.ConcurrentMap<K, V>
- このインタフェースでは、lock()
やunlock()
などの同時アクセスのためのメソッドが提供されます。トランザクションの実行を参照してください。
親トピック: 基本的なキャッシュ操作の実行の実行
NamedCache
インスタンスへの参照を取得するには、アプリケーションでSession
APIおよびCacheFactory
APIを使用できます。Session
APIでは、非静的なCoherenceセッションの使用および注入を可能にする簡潔なメソッド・セットが提供され、これはキャッシュの取得に推奨される方法です。対照的に、CacheFactory
APIでは、Coherenceの内部的な概念やサービスの知識を必要とする、多くの静的メソッドが公開されています。Session
APIにより、より効率的なライフサイクルおよび他のフレームワーク、特に注入を使用するフレームワークとの統合が可能になります。次の例では、デフォルトのセッション・プロバイダを使用してセッションを作成してから、Session.getCache
メソッドを使用してNamedCache
インスタンスへの参照を取得します。キャッシュの名前はパラメータとして含まれます。
import com.tangosol.net.*; ... Session session = Session.create(); NamedCache<Object, Object> cache = session.getCache("MyCache");
CoherenceSession
クラスはSession
インタフェースを実装し、アプリケーションがnew
演算子を使用できるようにします。たとえば:
import com.tangosol.net.*; ... Session session = new CoherenceSession(); NamedCache<Object, Object> cache = session.getCache("MyCache");
次の例では、CacheFactory.getCache
メソッドを使用してNamedCache
インスタンスへの参照を取得し、キャッシュの名前をパラメータとして含めます。
import com.tangosol.net.*; ... NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache");
Session
APIとCacheFactory
APIの両方は、必要に応じて基礎となるキャッシュ・サービスを開始します。キャッシュ・インスタンスは、キャッシュ構成ファイル(デフォルトでcoherence-cache-config.xml
)に定義されているキャッシュ・スキームを使用して作成されます。キャッシュ・スキームは、名前MyCache
にマップされます。キャッシュの構成を参照してください。
NamedCache
インスタンスでは、任意のタイプのキーと値を格納できます。ただし、キャッシュ・エントリを操作する場合は、型の安全性をアプリケーションで確保する必要があります。アプリケーションでは、特定の型のNamedCache
インスタンスを作成でき、APIレベルの型チェックも提供されます。NameCache型チェックの使用を参照してください。
キャッシュされたオブジェクトの要件
キャッシュのキーおよび値はシリアライズ可能である必要があります(たとえば、java.io.Serializable
またはCoherence Portable Object Formatのシリアライズ)。さらに、キャッシュ・キーはhashCode()
とequals()
メソッドの実装を提供する必要があり、これらのメソッドはクラスタ・ノード間で一貫性のある結果を返す必要があります。これは、hashCode()
およびequals()
の実装は、オブジェクトのシリアライズ可能な状態(つまり、オブジェクトの一時的でないフィールド)にのみ基づいている必要があることを示しています。String
、Integer
、Date
などのほとんどの組込みのJava型はこの要件を満たしています。一部のキャッシュの実装(特にパーティション・キャッシュ)では、等価の検証にキー・オブジェクトのシリアライズされた形式を使用し、equals()
でtrue
を返すキーは、同様の方法でシリアライズされる必要があり、ほとんどの組込みのJava型はこの要件を満たしています。Portable Object Formatの使用を参照してください
親トピック: 基本的なキャッシュ操作の実行の実行
Map
インタフェースで定義されているput
メソッドを使用して実行されます。put
メソッドは、エントリをキャッシュに追加して、指定したキーの前の値を返します。たとえば:String key = "k1"; String value = "Hello World!"; NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache"); cache.put(key, value);
putAll
メソッドは、単一のバルク・ロード操作で複数のエントリをキャッシュに追加する場合に使用され、エントリはMap
型のデータ構造内にある必要があります。キャッシュの事前ロードを参照してください。
親トピック: 基本的なキャッシュ操作の実行の実行
Map
インタフェースで定義されているget
メソッドを使用して実行されます。マップされている値は、指定したキーで返されます。たとえば:String key = "k1"; String value = "Hello World!"; NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache"); cache.put(key, value); System.out.println(cache.get(key));
親トピック: 基本的なキャッシュ操作の実行の実行
Map
インタフェースで定義されているremove
メソッドを使用して実行されます。指定したキーのマッピングはキャッシュから削除され、前の値が返されます。たとえば:String key = "k1"; String value = "Hello World!"; NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache"); cache.put(key, value); System.out.println(cache.get(key)); cache.remove(key);
親トピック: 基本的なキャッシュ操作の実行の実行
java.util.Map
インタフェースには、putIfAbsent
、replaceAll
、merge
などの操作を実行するためのデフォルトのメソッドが含まれています。Coherenceでは、多くのMap
メソッドの実装をオーバーライドして、これらの操作が分散環境で適切に実行されることを保証します。エントリ・プロセッサを使用して、ラムダ式を活用できるように、メソッドが再実装されています。メソッドは、NamedCache
インタフェースを使用する場合に使用できます。たとえば:String key = "k1"; String value = "Hello World!"; NamedCache<Object, Object> cache = CacheFactory.getCache("hello-example"); cache.putIfAbsent(key, value); System.out.println(cache.get(key));
ラムダ式は、必要な処理をエントリで実行する場合にも使用できます。たとえば、
cache.replaceAll((key, value) -> { value.setLastName(value.getLastName().toUpperCase()); return value; });
親トピック: 基本的なキャッシュ操作の実行の実行
この項には次のトピックが含まれます:
put
メソッドを使用して、キャッシュにデータをバルク・ロードできます。ただし、特にパーティション・キャッシュおよびレプリケート・キャッシュでは、put
をコールするたびにネットワーク・トラフィックが発生する場合があります。また、put
をコールするたびにキャッシュで置換されたばかりのオブジェクトが返され(java.util.Map
インタフェースで定義されている)、不要なオーバーヘッドが追加されます。
public static void bulkLoad(NamedCache cache, Connection conn) { Statement s; ResultSet rs; try { s = conn.createStatement(); rs = s.executeQuery("select key, value from table"); while (rs.next()) { Integer key = new Integer(rs.getInt(1)); String value = rs.getString(2); cache.put(key, value); } ... } catch (SQLException e) {...} }
かわりに、ConcurrentMap.putAll
メソッドを使用すると、キャッシュのロードを大幅に効率化できます。たとえば:
public static void bulkLoad(NamedCache cache, Connection conn) { Statement s; ResultSet rs; Map buffer = new HashMap(); try { int count = 0; s = conn.createStatement(); rs = s.executeQuery("select key, value from table"); while (rs.next()) { Integer key = new Integer(rs.getInt(1)); String value = rs.getString(2); buffer.put(key, value); // this loads 1000 items at a time into the cache if ((count++ % 1000) == 0) { cache.putAll(buffer); buffer.clear(); } } if (!buffer.isEmpty()) { cache.putAll(buffer); } ... } catch (SQLException e) {...} }
親トピック: キャッシュの事前ロード
Coherenceのパーティション・キャッシュに大量のデータ・セットを事前移入する際は、Coherenceのクラスタ・メンバーに作業を分散すると効率が向上する可能性があります。分散ロードを使用すると、クラスタのネットワーク帯域幅およびCPU処理能力の集積を活用することによって、データ・スループット率を高めることができます。分散ロードの実行時には、アプリケーションで次の事項を決定する必要があります。
ロードを実行するクラスタのメンバー
メンバー間でのデータ・セットの分割方法
メンバーの選択および作業の分割時は、基礎となるデータ・ソース(データベースやファイル・システムなど)に対する負荷をアプリケーションで考慮する必要があります。たとえば、問合せを同時に実行するメンバーが多すぎると、1つのデータベースでは対応しきれなくなる場合があります。
親トピック: キャッシュの事前ロード
この項では、簡単な分散ロードを実行する一般的なステップの概要について説明します。この例では、データがファイルに保存されていて、クラスタ内で記憶域が有効なすべてのメンバーに分散されることを前提としています。
記憶域が有効なメンバーのセットを取得します。たとえば、次の方法ではgetStorageEnabledMembers
メソッドを使用して、分散キャッシュ内で記憶域が有効なメンバーを取得します。
protected Set getStorageMembers(NamedCache cache) { return ((PartitionedService) cache.getCacheService()) .getOwnershipEnabledMembers(); }
記憶域が有効なクラスタのメンバー間で作業を分割します。たとえば、次のルーチンでは、メンバーに割り当てられたファイルの一覧が含まれるマップが、メンバーをキーとして返されます。
protected Map<Member, List<String>> divideWork(Set members, List<String> fileNames) { Iterator i = members.iterator(); Map<Member, List<String>> mapWork = new HashMap(members.size()); for (String sFileName : fileNames) { Member member = (Member) i.next(); List<String> memberFileNames = mapWork.get(member); if (memberFileNames == null) { memberFileNames = new ArrayList(); mapWork.put(member, memberFileNames); } memberFileNames.add(sFileName); // recycle through the members if (!i.hasNext()) { i = members.iterator(); } } return mapWork; }
各メンバーへのロードを実行するタスクを起動します。たとえば、タスクの起動にはCoherenceのInvocationService
などを使用します。この場合、LoaderInvocable
の実装では、memberFileNames
を反復して各ファイルを処理し、その内容をキャッシュにロードする必要があります。通常、クライアント上で実行されるキャッシュ処理は、LoaderInvocable
を使用して実行する必要があります。
public void load() { NamedCache cache = getCache(); Set members = getStorageMembers(cache); List<String> fileNames = getFileNames(); Map<Member, List<String>> mapWork = divideWork(members, fileNames); InvocationService service = (InvocationService) CacheFactory.getService("InvocationService"); for (Map.Entry<Member, List<String>> entry : mapWork.entrySet()) { Member member = entry.getKey(); List<String> memberFileNames = entry.getValue(); LoaderInvocable task = new LoaderInvocable(memberFileNames, cache.getCacheName()); service.execute(task, Collections.singleton(member), this); } }
親トピック: キャッシュの事前ロード
NamedCache
インタフェースで定義されるclear
またはtruncate
メソッドを使用してクリアできます。clear
メソッドにより、メモリーおよびCPUオーバーヘッドが増加するため、分散キャッシュのクリアには一般にお薦めしません。別の方法として、truncate
メソッドを使用できます。たとえば:String key = "k1"; String value = "Hello World!"; NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache"); cache.put(key, value); System.out.println(cache.get(key)); Cache.truncate;
truncate
メソッドでは、メモリーおよびCPUリソースを効率的に使用できるため、大きなキャッシュやリスナーを使用するキャッシュをクリアする場合に最適なオプションになります。truncate
メソッドは、フロント・マップおよびバック・マップの両方をクリアするため、ニア・キャッシュのクリアにも最適です。truncate
メソッドでエントリが削除されたかどうかは、リスナー、トリガーおよびインターセプタで監視できません。ただし、CacheLifecycleEvent
イベントが発生し、この操作の実行がすべてのサブスクライバに通知されます。
親トピック: 基本的なキャッシュ操作の実行の実行
CacheFactory.release
メソッドを使用して、指定されたキャッシュのインスタンスに関連付けられているローカル・リソースを解放するようにしてください。キャッシュを解放すると、キャッシュは使用できなくなりますが、クラスタ全体でのキャッシュへの他の参照またはキャッシュの内容は影響を受けません。たとえば:String key = "k1"; String value = "Hello World!"; NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache"); cache.put(key, value); System.out.println(cache.get(key)); CacheFactory.releaseCache(cache);
親トピック: 基本的なキャッシュ操作の実行の実行
CacheFactory
クラスを使用して作成されるキャッシュは、CacheFactory.destroy
メソッドを使用して破棄できます。destroy
メソッドは、クラスタ全体で指定されたキャッシュを破棄します。キャッシュへの参照が無効化され、キャッシュされたデータがクリアされて、すべてのリソースが解放されます。NamedCache.clear
メソッドは、分散環境でメモリーとCPUの両方の負荷が高くなるタスクになる可能性があるため、多くの場合destroy
メソッドの方が適しています。たとえば:String key = "k1"; String value = "Hello World!"; NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache"); cache.put(key, value); System.out.println(cache.get(key)); CacheFactory.destroyCache(cache);
親トピック: 基本的なキャッシュ操作の実行の実行
セッションをクローズするには、close
メソッドを使用します。たとえば:
String key = "k1"; String value = "Hello World!"; try(Session session = Session.create()) { NamedCache<Object, Object> cache = session.getCache("MyCache"); cache.put(key, value); System.out.println(cache.get(key)); session.close(); } catch (Exception e){ }
親トピック: 基本的なキャッシュ操作の実行の実行
com.tangosol.net.AsyncNameCache<K, V
インタフェースにより、キャッシュ操作をパラレルに完了できます。このインタフェースでは、Java CompletableFuture
クラスを使用し、このクラスでは、完了または例外(あるいは両方)のコールバックを提供して、複数の非同期コールを連鎖して順に実行し、パラレルに実行しているすべてのコールが完了するまで待機します。NameCache
操作を非同期に実行すると、スループットが改善し、ユーザー・インタフェースの応答性が向上します。Coherenceの例では、非同期キャッシュ操作の実行の追加の例を提供します。Oracle CoherenceのインストールのCoherenceの非同期機能のサンプルを参照してください。非同期キャッシュ操作を実行するには、CompletableFuture
クラスを使用して、Future
インタフェースを実装する必要があります。たとえば:
import com.tangosol.net.AsyncNamedCache; import com.tangosol.net.CacheFactory; import com.tangosol.net.NamedCache; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; public class HelloWorld { public static void main(String[] args) throws ExecutionException, InterruptedException { String key = "k1"; String value = "Hello World!"; NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache"); AsyncNamedCache<Object, Object> as = cache.async(); Future future = as.put(key, value); future.get(); CompletableFuture cf = as.get(key); System.out.println(cf.get()); CompletableFuture cfremove = as.remove(key); System.out.print("Removing key/value: " + cfremove.get() + "\n" ); System.out.println("The key/value is: " + future.get()); } }
親トピック: 基本的なキャッシュ操作の実行の実行
Session
またはCacheFactory
APIのいずれかを使用している場合、厳密に型指定されたNamedCache
インスタンスをリクエストできます。デフォルトでは、NamedCache<Object, Object>
インスタンスが返されます。これは、NamedCache
インスタンスを作成および使用するための最も柔軟なメカニズムですが、キャッシュ・インスタンスとのやり取りに必要なキーと値の型をアプリケーションで設定する必要があります。次の例では、アプリケーションで使用する任意のタイプのオブジェクトを格納します。
NamedCache<Object,Object> cache = session.getCache("MyCache");
または
NamedCache<Object,Object> cache = CacheFactory.getCache("MyCache");
getCache
メソッドは、型チェックすることなく、必要に応じて特定の型のNamedCache
インスタンスをリクエストする場合に使用できます。TypeAssertion
インタフェースは、getCache
メソッドともに使用され、NamedCache
インスタンスで使用されるキーと値の型の正確性をアサートします。このメソッドは、キャッシュがRAW型を使用する必要があることをアサートする場合に使用できます。たとえば:
NamedCache<Object, Object> cache = session.getCache("MyCache", TypeAssertion.withRawTypes());
同様に、CacheFactory
を使用している場合、
NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache", TypeAssertion.withRawTypes());
型の安全性を強化するために、キャッシュを作成して、キャッシュで使用されるキーと値の型を明示的にアサートできます。たとえば、キャッシュを作成して、キーと値の型がString
である必要があることをアサートするには、アプリケーションで次を使用できます。
NamedCache<String, String> cache = session.getCache("MyCache", TypeAssertion.withTypes(String.class, String.class));
NameCache
インスタンスは、アサートされた型に準拠する必要はなく、無視することもできますが、コンパイル時に警告メッセージが表示されます。たとえば:
NamedCache cache = session.getCache("MyCache", TypeAssertion.withTypes(String.class, String.class));
同様に、RAW型を使用し、ネーム・キャッシュ・インスタンスで特定の型を使用できることをアサートすることを、アプリケーションで選択することもできます。ただし、どちらの場合も、型がチェックされないままでは、エラーが発生することがあります。たとえば:
NamedCache<String, String> cache = session.getCache("MyCache", TypeAssertion.withRawTypes());
型の安全性を最も強くするには、特定の型をキャッシュ定義の一部として、キャッシュ構成ファイルに宣言することもできます。キャッシュ定義の部分として構成された型と異なる型をアプリケーションが使用すると、ランタイム・エラーが発生します。次の例では、String
型のキーと値のみをサポートするキャッシュを構成します。
<cache-mapping> <cache-name>MyCache</cache-name> <scheme-name>distributed</scheme-name> <key-type>String</key-type> <value-type>String</value-type> </cache-mapping>
最後に、明示的な型チェックの無効化をアプリケーションで選択できます。型チェックが無効の場合、型の安全性はアプリケーションで確保する必要があります。
NamedCache<Object, Object> cache = session.getCache("MyCache", TypeAssertion.withoutTypeChecking());
親トピック: 基本的なキャッシュ操作の実行の実行