2.4. 非同期のレプリケーション
すべてのクラスター化されたキャッシュモードは、<replicated-cache/>
、<distributed-cache>
、または <invalidation-cache/>
要素上で mode="ASYNC"
属性と非同期通信を使用するように設定できます。
非同期通信では、送信元ノードは操作のステータスについて他のノードから確認応答を受け取ることはありません。そのため、他のノードで成功したかどうかを確認する方法はありません。
非同期通信はデータに不整合を引き起こす可能性があり、結果を推論するのが難しいため、一般的に非同期通信は推奨しません。ただし、速度が一貫性よりも重要であり、このようなケースでオプションが利用できる場合があります。
Asynchronous API
非同期 API を使用すると、ユーザースレッドをブロックしなくても同期通信を使用できます。
注意点が 1 つあります。非同期操作はプログラムの順序を保持しません。スレッドが cache.putAsync(k, v1); cache.putAsync(k, v2)
を呼び出す場合の k
の最終的な値は v1
または v2
のいずれかになります。非同期通信を使用する場合の利点は、最終的な値をあるノードで v1
にして別のノードで v2
にすることができないことです。
2.4.1. 非同期レプリケーションのある戻り値
Cache
インターフェイスは java.util.Map
を拡張するため、put(key, value)
や remove(key)
などの書き込みメソッドはデフォルトで以前の値を返します。
戻り値が正しくないことがあります。
-
Flag.IGNORE_RETURN_VALUE
、Flag.SKIP_REMOTE_LOOKUP
、またはFlag.SKIP_CACHE_LOAD
でAdvancedCache.withFlags()
を使用する場合。 -
キャッシュに
unreliable-return-values="true"
が設定されている場合。 - 非同期通信を使用する場合。
- 同じキーへの同時書き込みが複数あり、キャッシュトポロジーが変更された場合。トポロジーの変更により、Data Grid は書き込み操作を再試行します。また、再試行操作の戻り値は信頼性がありません。
トランザクションキャッシュは、3 と 4 の場合、正しい以前の値を返します。しかし、トランザクションキャッシュには gotcha: in distributed モードもあり、read-committed 分離レベルは、繰り返し可能な読み取りとして実装されます。つまり、この "double-checked locking" 例は機能しません。
Cache cache = ... TransactionManager tm = ... tm.begin(); try { Integer v1 = cache.get(k); // Increment the value Integer v2 = cache.put(k, v1 + 1); if (Objects.equals(v1, v2) { // success } else { // retry } } finally { tm.commit(); }
これを実装する適切な方法として、cache.getAdvancedCache().withFlags(Flag.FORCE_WRITE_LOCK).get(k)
を使用します。
最適化されたロックを持つキャッシュでは、書き込みは古い以前の値を返すことができます。書き込み skew チェックでは、古い値を回避できます。