25 基本的なキャッシュ操作の実行
この章の内容は次のとおりです。
- NamedMap APIの概要
com.tangosol.net.NamedMap<K, V>
インタフェースは、アプリケーションがキャッシュ・インスタンスを取得して、それとやりとりするために使用する主要インタフェースです。 - キャッシュ・インスタンスの取得
NamedMap
インスタンスへの参照を取得するために、アプリケーションはSession
APIおよびCacheFactory
APIを使用できます。 - キャッシュput操作の実行
基本的なキャッシュput
操作は、Map
インタフェースで定義されているput
メソッドを使用して実行されます。 - キャッシュget操作の実行
基本的なキャッシュget操作は、Map
インタフェースで定義されているget
メソッドを使用して実行されます。 - キャッシュ削除操作の実行
基本的なキャッシュ削除操作は、Map
インタフェースで定義されているremove
メソッドを使用して実行されます。 - デフォルトのマップ操作の使用
Coherenceでは、多くのMap
メソッドの実装をオーバーライドして、これらの操作が分散環境で適切に実行されることを保証します。 - キャッシュの事前ロード
キャッシュの事前ロードは、アプリケーションでデータを使用する前にキャッシュに移入する場合に使用される一般的なシナリオです。 - キャッシュのクリア
マップの内容は、NamedMap
インタフェースで定義されるclear
またはtruncate
メソッドを使用してクリアできます。 - キャッシュの解放
キャッシュが不要になったアプリケーションでは、NamedMap.release
メソッドを使用して、指定されたキャッシュのインスタンスに関連付けられているローカル・リソースを解放する必要があります。 - キャッシュの破棄
Session
またはCacheFactory
クラスを使用して作成されるNamedMapsまたはNamedCachesは、NamedMap.destroy
メソッドを使用して破棄できます。 - セッションのクローズ
セッションが不要になった場合、アプリケーションはそのセッションをクローズする必要があります。 - NamedMap操作の非同期実行
com.tangosol.net.AsyncNamedMap<K, V>
インタフェースにより、キャッシュ操作を並列に完了できます。 - NamedMap型チェックの使用
Coherenceには、明示的な型を使用してSession
またはCacheFactory
APIを使用する場合、厳密に型指定されたNamedMap
インスタンスをリクエストする機能が含まれています。
親トピック: データ・グリッド操作の実行
NamedMap APIの概要
com.tangosol.net.NamedMap<K, V>
インタフェースは、アプリケーションがキャッシュ・インスタンスを取得して、それとやりとりするために使用する主要インタフェースです。NamedMap<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()
などの同時アクセスのためのメソッドが提供されます。トランザクションの実行を参照してください。
ノート:
NamedMap
では使用できない有効期限付きのput
を発行する場合は、NamedMap
を拡張するcom.tangosol.net.NamedCache<K, V>
インタフェースを使用できます。後続の項の例に示すように、Session APIを使用してNamedCache
インスタンスを取得できます。
親トピック: 基本的なキャッシュ操作の実行の実行
キャッシュ・インスタンスの取得
NamedMap
インスタンスへの参照を取得するために、アプリケーションではSession
APIとCacheFactory
APIを使用できます。Session
APIでは、非静的なCoherenceセッションの使用および注入を可能にする簡潔なメソッド・セットが提供され、これはキャッシュの取得に推奨される方法です。対照的に、CacheFactory
APIでは、Coherenceの内部的な概念やサービスの知識を必要とする、多くの静的メソッドが公開されています。Session
APIにより、より効率的なライフサイクルおよび他のフレームワーク、特に注入を使用するフレームワークとの統合が可能になります。
次の例では、デフォルトのセッション・プロバイダを使用してセッションを作成してから、Session.getCache
メソッドを使用してNamedMap
インスタンスへの参照を取得します。キャッシュの名前はパラメータとして含まれます。
import com.tangosol.net.*;
...
Session session = Session.create();
NamedMap<Object, Object> map = session.getMap("MyCache");
CoherenceSession
クラスはSession
インタフェースを実装し、アプリケーションがnew
演算子を使用できるようにします。たとえば:
import com.tangosol.net.*;
...
Session session = new CoherenceSession();
NamedMap<Object, Object> map = session.getMap("MyCache");
次の例では、CacheFactory.getCache
メソッドを使用してNamedCache
インスタンスへの参照を取得し、キャッシュの名前をパラメータとして含めます。
import com.tangosol.net.*;
...
NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache");
ノート:
CacheFactoryを使用してNamedCache
インスタンスを取得できますが、Session APIを使用してNamedMap
およびNamedCache
インスタンスを取得することをお薦めします。
Session
APIとCacheFactory
APIの両方は、必要に応じて基礎となるキャッシュ・サービスを開始します。キャッシュ・インスタンスは、キャッシュ構成ファイル(デフォルトでcoherence-cache-config.xml
)に定義されているキャッシュ・スキームを使用して作成されます。キャッシュ・スキームは、名前MyCache
にマップされます。キャッシュの構成を参照してください。
NamedMap
インスタンスでは、任意のタイプのキーと値を格納できます。ただし、キャッシュ・エントリを操作する場合は、型の安全性をアプリケーションで確保する必要があります。アプリケーションでは、特定の型のNamedMap
インスタンスを作成でき、APIレベルの型チェックも提供されます。NamedMap型チェックの使用を参照してください。
キャッシュされたオブジェクトの要件
キャッシュのキーおよび値はシリアライズ可能である必要があります(たとえば、java.io.Serializable
またはCoherence Portable Object Formatのシリアライズ)。さらに、キャッシュ・キーはhashCode()
とequals()
メソッドの実装を提供する必要があり、これらのメソッドはクラスタ・ノード間で一貫性のある結果を返す必要があります。これは、hashCode()
およびequals()
の実装は、オブジェクトのシリアライズ可能な状態(つまり、オブジェクトの一時的でないフィールド)にのみ基づいている必要があることを示しています。String
、Integer
、Date
などのほとんどの組込みのJava型はこの要件を満たしています。一部のキャッシュの実装(特にパーティション・キャッシュ)では、等価の検証にキー・オブジェクトのシリアライズされた形式を使用し、equals()
でtrue
を返すキーは、同様の方法でシリアライズされる必要があり、ほとんどの組込みのJava型はこの要件を満たしています。Portable Object Formatの使用を参照してください
親トピック: 基本的なキャッシュ操作の実行の実行
キャッシュput操作の実行
put
操作は、Map
インタフェースで定義されているput
メソッドを使用して実行されます。put
メソッドは、キャッシュにエントリを追加し、指定されたキーの前の値を返します。たとえば:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);"
putAll
メソッドは、単一のバルク・ロード操作で複数のエントリをキャッシュに追加する場合に使用され、エントリはMap
型のデータ構造内にある必要があります。キャッシュの事前ロードを参照してください。
親トピック: 基本的なキャッシュ操作の実行の実行
キャッシュget操作の実行
Map
インタフェースで定義されているget
メソッドを使用して実行されます。指定されたキーに対して、マップされた値が返されます。たとえば:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
親トピック: 基本的なキャッシュ操作の実行の実行
キャッシュ削除操作の実行
Map
インタフェースで定義されているremove
メソッドを使用して実行されます。指定されたキーのマッピングがキャッシュから削除され、前の値が戻されます。たとえば:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
map.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));
ラムダ式は、必要な処理をエントリで実行する場合にも使用できます。たとえば、
map.replaceAll((key, value) -> { value.setLastName(value.getLastName().toUpperCase()); return value; });
親トピック: 基本的なキャッシュ操作の実行の実行
キャッシュの事前ロード
この項には次のトピックが含まれます:
キャッシュへのデータのバルク・ロード
put
メソッドを使用して、キャッシュにデータをバルク・ロードできます。ただし、特にパーティション・キャッシュおよびレプリケート・キャッシュでは、put
をコールするたびにネットワーク・トラフィックが発生する場合があります。また、put
をコールするたびにキャッシュで置換されたばかりのオブジェクトが返され(java.util.Map
インタフェースで定義されている)、不要なオーバーヘッドが追加されます。
public static void bulkLoad(NamedMap map, 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(NamedMap map, 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(NamedMap map) { return ((PartitionedService) map.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); } }
親トピック: キャッシュの事前ロード
キャッシュのクリア
NamedMap
インタフェースで定義されるclear
またはtruncate
メソッドを使用してクリアできます。clear
メソッドを使用すると、メモリーおよびCPUのオーバーヘッドが大きくなる可能性があり、通常、分散キャッシュをクリアすることはお薦めしません。別の方法として、truncate
メソッドを使用できます。たとえば:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
map.truncate();
truncate
メソッドでは、メモリーおよびCPUリソースを効率的に使用できるため、大きなキャッシュやリスナーを使用するキャッシュをクリアする場合に最適なオプションになります。truncate
メソッドは、フロント・マップおよびバック・マップの両方をクリアするため、ニア・キャッシュのクリアにも最適です。truncate
メソッドでエントリが削除されたかどうかは、リスナー、トリガーおよびインターセプタで監視できません。ただし、CacheLifecycleEvent
イベントが発生し、この操作の実行がすべてのサブスクライバに通知されます。
親トピック: 基本的なキャッシュ操作の実行の実行
キャッシュの解放
NamedMap.release
メソッドを使用して、指定されたキャッシュのインスタンスに関連付けられているローカル・リソースを解放するようにしてください。キャッシュを解放すると、そのアプリケーションは使用できなくなりますが、クラスタ全体のキャッシュの内容や、キャッシュに対する他の参照には影響しません。たとえば:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
map.release();
親トピック: 基本的なキャッシュ操作の実行の実行
キャッシュの破棄
Session
またはCacheFactory
クラスを使用して作成されるNamedMapsまたはNamedCachesは、NamedMap.destroy
メソッドを使用して破棄できます。destroy
メソッドは、クラスタ全体で指定されたキャッシュを破棄します。キャッシュへの参照が無効化され、キャッシュされたデータがクリアされて、すべてのリソースが解放されます。NamedMap.clear()
メソッドは、分散環境でメモリーとCPUの両方の負荷が高くなるタスクになる可能性があるため、多くの場合destroy
メソッドの方が適しています。たとえば:
String key = "k1";
String value = "Hello World!";
// obtain a session
Session session = ...
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
map.destroy();
親トピック: 基本的なキャッシュ操作の実行の実行
セッションのクローズ
セッションをクローズするには、close
メソッドを使用します。たとえば:
String key = "k1";
String value = "Hello World!";
try(Session session = Session.create()) {
NamedMap<Object, Object> map = session.getMap("MyCache");
map.put(key, value);
System.out.println(map.get(key));
session.close();
}
catch (Exception e){
...
}
親トピック: 基本的なキャッシュ操作の実行の実行
NamedMap操作の非同期実行
com.tangosol.net.AsyncNamedMap<K, V>
インタフェースにより、キャッシュ操作を並列に完了できます。このインタフェースでは、Java CompletableFuture
クラスを使用し、このクラスでは、完了または例外(あるいは両方)のコールバックを提供して、複数の非同期コールを連鎖して順に実行し、パラレルに実行しているすべてのコールが完了するまで待機します。NamedMap
操作を非同期に実行すると、スループットが改善し、ユーザー・インタフェースの応答性が向上します。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!"; NamedMap<Object, Object> map = CacheFactory.getCache("MyCache"); AsyncNamedMap<Object, Object> as = map.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()); } }
親トピック: 基本的なキャッシュ操作の実行の実行
NamedMap型チェックの使用
Session
またはCacheFactory
APIのいずれかを使用している場合、厳密に型指定されたNamedMap
インスタンスをリクエストできます。デフォルトでは、NamedMap<Object, Object>
インスタンスが返されます。これは、NamedMap
インスタンスを作成および使用するための最も柔軟なメカニズムですが、キャッシュ・インスタンスとのやり取りに必要なキーと値の型をアプリケーションで設定する必要があります。
NamedMap<Object,Object> map = session.getMap("MyCache");
NamedCache<Object,Object> cache = CacheFactory.getCache("MyCache");
getCache
またはgetMap
メソッドは、型チェックすることなく、必要に応じて特定の型のNamedCache
またはNamedMap
インスタンスをリクエストする場合に使用できます。TypeAssertion
インタフェースは、getCache
またはNamedCache
メソッドともに使用され、NamedCache
またはNamedMap
インスタンスで使用されるキーと値の型の正確性をアサートします。このメソッドは、キャッシュがRAW型を使用する必要があることをアサートする場合に使用できます。たとえば:NamedMap<Object, Object> map = session.getMap("MyCache", TypeAssertion.withRawTypes());
CacheFactory
を使用している場合、NamedCache<Object, Object> cache = CacheFactory.getCache("MyCache", TypeAssertion.withRawTypes());
String
である必要があることをアサートするには、アプリケーションで次を使用できます。NamedMap<String, String> map = session.getMap("MyCache", TypeAssertion.withTypes(String.class, String.class));
NamedMap
インスタンスは、アサートされた型に準拠する必要はなく、無視することもできますが、コンパイル時に警告メッセージが表示されます。たとえば:NamedMap map = session.getCache("MyCache", TypeAssertion.withTypes(String.class, String.class));
NamedMap
インスタンスで特定の型を使用できることをアサートすることを、アプリケーションで選択することもできます。ただし、どちらの場合も、型がチェックされないままでは、エラーが発生することがあります。たとえば:NamedMap<String, String> map = 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> map = session.getMap("MyCache", TypeAssertion.withoutTypeChecking());
親トピック: 基本的なキャッシュ操作の実行の実行