使用Infinispan在同一过程中进行隔离

时间:2011-08-22 16:35:41

标签: java transactions atomikos infinispan

我正在围绕Infinispan缓存和Atomikos事务管理器构建应用程序。我发现事务隔离不适用于在同一JVM上的两个不同线程中打开的事务。

使用以下代码实现缓存:

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.tmLookuporg.infinispan.transaction.lookup.TransactionManagerLookup的简单实现,返回configure 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;
}

由于缓存被配置为隔离,我希望在阅读器和编写器之间有不同的pojo实例,并且只有在提交了writer的事务之后才能看到更改。

但是我得到了以下输出:

[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

1 个答案:

答案 0 :(得分:3)

Infinispan equivalent to ehcache's copyOnRead and copyOnWrite

的底部看看Manik Surtani的回答

您应该启用storeAsBinary选项以获得正确的行为。