Изоляция в том же процессе с Infinispan - PullRequest
3 голосов
/ 22 августа 2011

Я создаю приложение на основе кэша Infinispan и менеджера транзакций Atomikos.Я обнаружил, что изоляция транзакции не работает для транзакций, открытых в двух разных потоках на одной и той же виртуальной машине Java.

Кэш-память создается с использованием следующего кода:

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;
}

Поскольку кэш настроен для изоляции, я ожидал, что между читателем и писателем будут разные экземпляры 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

Таким образом, в основном, кеш работает как хэш-карта, поскольку он возвращает один и тот же экземпляр pojo для обоих потоков.

Вопрос : я что-то упустил в конфигурации или в ожидаемом поведении?

Я довольноуверен, что менеджер транзакций работает так, как я могу получать сообщения журнала от Atomikos, указывающие на начало отдельных транзакций как на читателе, так и на писателе.

Однако я попробовал тот же тест, используя Ehcache вместо Infinispan, и получил ожидаемые результаты.Сравнивая журналы между двумя тестами, я обнаружил похожие сообщения, единственное очевидное различие заключается в отсутствии идентификатора транзакции для Infinispan:

INFO  atomikos  - addParticipant [...]

против

INFO  atomikos ehcache-txid=0 - addParticipant

1 Ответ

3 голосов
/ 23 августа 2011

Посмотрите на ответ Маника Суртани внизу Infinispan, эквивалентный копиям ehcache copyOnRead и copyOnWrite

Вероятно, вы должны включить опцию storeAsBinary, чтобы получить правильное поведение.

...