Java 8 (OpenJDK 64 ビット サーバー VM ベンダー: Azul Systems, Inc. バージョン: 25.262 -b19)
複数のインスタンスを起動するときにアプリケーションの起動を制御するために、Mutex と呼ばれる PESSIMISTIC ロッキング キャッシュを作成しました。これは、クラスターを「ロック」して、1 つのインスタンスがキャッシュをロードし、他のインスタンスが待機できるようにするために使用されます。ロックを取得する最初のインスタンスは、データベースを読み取り、すべて OPTIMISTIC ロックとして構成されている他の多くのキャッシュをロードします。これらのキャッシュの「プット」はすべて、外側の Mutex トランザクション内で発生します。OPTMISTIC キャッシュは state-transfer enabled=true で定義されているため、データベースからキャッシュをロードするインスタンスが完了し、外部トランザクションをコミットして Mutex ロックを解放すると、キャッシュもすべてのインスタンスで更新されます。
OPTIMISTIC キャッシュをロードするとき、CACHE1 のエントリを使用して CACHE2 のロードを駆動することがあります (より意味のある名前がありますが、ここではその詳細は重要ではありません)。したがって、CACHE1 をロードしたら、CACHE1.values() を使用してエントリを CACHE2.put() に編成します。
今問題に...
V9.4.20.Final (およびそれ以下) では、上記のプロセスが機能します。V10.x (V.11.0.5.Final も) では、これは機能しません。コードをデバッグしたところ、V10.x で CACHE2 をロードしようとすると、CACHE1.values() で CACHE1.values() に書き込まれたエントリ (すべてのキャッシュは isolation="READ_COMMITTED") が表示されないことがわかりました。この同じコードが V9 で機能することを確認するために、 CACHE1.values() は同じトランザクション内にあるため期待どおりに値を返し、エントリを表示できるはずです。
V10 で外部 Mutex トランザクションがない場合、または CACHE1 を読み取ろうとする前に外部 Mutex トランザクションをコミットしない場合、すべてが機能します。
質問:
入れ子になったトランザクションで書き込まれたエントリが、それらを書き込んだプロセスから見えなくなるように、トランザクション性が変更されましたか?
コンテナー トランザクション マネージャーの動作が異なるのではないかと疑って Weblogic 12.2.13 を試しましたが、違います。V10 が Weblogic 上の V9 で動作すると失敗します。
zip (eclipse/gradle プロジェクト) で完全なコード再現を提供できますが、ここにコード スニペットを示します。
CacheServiceImpl には、exclusivePutAndGetAll というメソッドがあり、「Mutex」親トランザクションがコミットされる前または後にエントリを読み取るかどうかを制御するブール値で呼び出すことができる LOCK_KEY という名前でロックします。
@Override
public <K, V> Collection<V> exclusivePutAndGetAll(String cacheName, Map<K, V> values, boolean insideMutex) throws Exception {
Collection<V> returnValues = null;
LOGGER.debug("mutex manager is " + mutexManager.getManagerHash());
LOGGER.debug("cache manager is " + cacheManager.getManagerHash());
LOGGER.info("Acquiring mutex lock before starting context");
mutexManager.startTransactionAndAcquireMutex("LOCK_KEY");
putAll(cacheName, values);
if (insideMutex) {
returnValues = getAll(cacheName); // this only works and returns values with V9 !!
}
mutexManager.commitTransaction();
LOGGER.info("Mutex lock released after starting context.");
if (!insideMutex) {
returnValues = getAll(cacheName);
}
return returnValues;
}
そして、トランザクションを開始し、提供された「LOCK_KEY」で Mutex と呼ばれるキャッシュをロックする、mutexManager の startTransactionAndAcquireMutex を次に示します。
@Override
public boolean startTransactionAndAcquireMutex(String mutexName) {
final TransactionManager transactionManager = mutexCache.getTransactionManager();
LOGGER.debug("Mutex cache TransactionManager is " + transactionManager.getClass());
try {
transactionManager.begin();
} catch (NotSupportedException | SystemException ex) {
throw new CacheException("Unable to start transaction for mutex " + mutexName, ex);
}
return acquireMutex(mutexName);
}
ロックを取得するミューテックスマネージャーは次のとおりです。
@Override
public boolean acquireMutex(String mutexName) {
final TransactionManager transactionManager = mutexCache.getTransactionManager();
boolean lockResult = false;
try {
if (transactionManager.getStatus() == Status.STATUS_ACTIVE) {
lockResult = mutexCache.lock(mutexName);
}
} catch (final SystemException ex) {
throw new CacheException("Unable to lock mutex " + mutexName, ex);
}
return lockResult;
}
そして最後に XML のキャッシュ構成
<?xml version="1.0" encoding="UTF-8"?>
<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:10.1 http://www.infinispan.org/schemas/infinispan-config-10.1.xsd"
xmlns="urn:infinispan:config:10.1">
<jgroups>
<stack-file name="tcp-cdl" path="cluster-jgroups.xml"/>
</jgroups>
<cache-container name="SampleCacheManager" statistics="true">
<transport stack="tcp-cdl"/>
<jmx duplicate-domains="true"/>
<replicated-cache-configuration name="replicated-cache-template" statistics="true" mode="SYNC" remote-timeout="120000">
<locking isolation="READ_COMMITTED" acquire-timeout="120000" write-skew="false" concurrency-level="150" striping="false"/>
<state-transfer enabled="true" timeout="240000" chunk-size="10000"/>
<transaction
transaction-manager-lookup="org.infinispan.transaction.lookup.GenericTransactionManagerLookup"
mode="NON_XA"
locking="OPTIMISTIC">
</transaction>
</replicated-cache-configuration>
<replicated-cache name="Mutex" configuration="replicated-cache-template">
<transaction locking="PESSIMISTIC" />
</replicated-cache>
</cache-container>
</infinispan>