2011-08-22 23 views
3

我正在圍繞Infinispan緩存和Atomikos事務管理器構建應用程序。我發現事務隔離不適用於在同一個JVM上的兩個不同線程中打開的事務。與Infinispan在同一進程中的隔離

的緩存使用下面的代碼實例化:

cacheManager = new DefaultCacheManager(); 
final Configuration config = new Configuration().fluent().transactionManagerLookup(this.tmLookup).recovery().locking() 
    .isolationLevel(IsolationLevel.READ_COMMITTED).build(); 
this.cacheManager.defineConfiguration("Gruik", config); 
this.cache = this.cacheManager.getCache("Gruik"); 

隨着this.tmLookup是一個簡單的實施org.infinispan.transaction.lookup.TransactionManagerLookup返回配置Atomikos公司事務管理。

我通過用單個值填充緩存來設置一個小測試,並且我在兩個線程中分別在單獨的事務中啓動讀取器和寫入器。基本上,作者將獲得存儲在緩存中的值,更改該值並將其保存到緩存中。另一方面,在不同階段讀取並顯示值:在作者執行任何更改之前,在作者更改pojo之後,在作者保存更新後的pojo並最終在作者事務提交之後。

作家代碼:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
public void performTrans() throws InterruptedException, BrokenBarrierException { 
    LOGGER.info("Wait to start"); 
    pBarrier.await(); // 1 
    final Pojo entity = cache.get(KEY); 
    LOGGER.info("Start entity: {}", entity); 
    pBarrier.await(); // 2 
    entity.setValue(entity.getValue() + 42); 
    LOGGER.info("Entity changed wait for reader"); 
    pBarrier.await(); // 3 
    cache.put(KEY, entity); 
    LOGGER.info("Entity saved wait for reader"); 
    pBarrier.await(); // 4 
} 

讀者代碼:

public void performTrans() throws InterruptedException, BrokenBarrierException { 
    LOGGER.info("Wait to start"); 
    pBarrier.await(); // 1 
    final Pojo entity = cache.get(KEY); 
    LOGGER.info("Start entity: {}", entity); 
    pBarrier.await(); // 2 
    LOGGER.info("Wait writer to make changes"); 
    pBarrier.await(); // 3 
    LOGGER.info("After change: {}", entity); 
    pBarrier.await(); // 4 
    Pojo newEntity = cache.get(KEY); 
    LOGGER.info("After save: {}", newEntity); 
    pBarrier.await(); // 5 
    newEntity = cache.get(KEY); 
    LOGGER.info("After transaction end: {}", newEntity); 
} 

爲了追蹤由我實現這個POJO toString()這樣緩存返回的實體:

public String toString() { 
    return "[" + System.identityHashCode(this) + "] id: " + this.id + ", value: " + this.value; 
} 

由於緩存配置爲隔離,我預計會有不同t閱讀者和作者之間的pojo實例,並且只有在作者的事務提交後才能看到更改。

但是我得到了以下的輸出:

[Reader] - Wait to start 
[Writer] - Wait to start 
[Writer] - Start entity: [19682788] id: 1, value: 666 
[Reader] - Start entity: [19682788] id: 1, value: 666 
[Reader] - Wait writer to make changes 
[Writer] - Entity changed wait for reader 
[Reader] - After change: [19682788] id: 1, value: 708 
[Writer] - Entity saved wait for reader 
[Reader] - After save: [19682788] id: 1, value: 708 
[Reader] - After transaction end: [19682788] id: 1, value: 708 

所以基本上,緩存執行像一個HashMap,因爲它返回兩個線程在同一POJO實例。

問題是我錯過了配置中或預期的行爲?

我很確定事務管理器正在工作,因爲我可以從Atomikos獲得日誌消息,指示讀寫器上的不同事務的開始。

但是我嘗試了使用Ehcache而不是Infinispan的相同測試,並且得到了預期的結果。兩次測試之間的日誌比較,我發現了類似消息的唯一明顯的區別是對的Infinispan沒有事務ID:

INFO atomikos - addParticipant [...] 

VS

INFO atomikos ehcache-txid=0 - addParticipant 

回答

3

底部看看馬尼克Surtani的回答的Infinispan equivalent to ehcache's copyOnRead and copyOnWrite

您應該可以啓用storeAsBinary選項以獲得正確的行爲。

+0

我試過了,行爲仍然不正確。即:兩個事務中返回的對象仍然相同。 – gabuzo

+0

即使使用討論中提供的參數,Infinispan也沒有執行copyOnRead或copyOnWriter的問題確實存在問題。問題https://issues.jboss.org/browse/ISPN-1345跟蹤此問題。 – gabuzo