Статьи

Римейк транзакции в Infinispan 5.1

Если вы когда-либо использовали Infinispan транзакционным способом, вам может быть очень интересна эта статья, так как она описывает некоторые очень существенные улучшения в версии 5.1 «Brahma» (выпущенной с 5.1.Beta1):

  • Начиная с этого выпуска, кэш Infinispan может быть доступен как транзакционно, так и нетранзакционно. Режим смешанного доступа больше не поддерживается (обратная совместимость все еще поддерживается, см. Ниже). Есть несколько причин, по которым следует идти по этому пути, но одной из наиболее важных результатов этого решения является более четкая семантика того, как управляется параллелизм между несколькими запросчиками для одной и той же записи в кэше.
  • начиная с 5.1, поддерживаемые модели транзакций являются оптимистичными и пессимистичными . Оптимистическая модель является улучшением по сравнению с существующей моделью транзакции по умолчанию, полностью откладывая получение блокировки до времени подготовки транзакции. Это уменьшает длительность захвата блокировки и увеличивает пропускную способность; также избегает тупиков. С пессимистической моделью, широкие блокировки кластера получают при каждой записи и снимают только после завершения транзакции (см. Ниже).

Транзакционный или нетранзакционный кеш?

Вам, как пользователю, решать, хотите ли вы определить кеш как транзакционный или нет. По умолчанию кэши Infispan не являются транзакционными. Кэш можно сделать транзакционным, изменив
атрибутactionactionMode :

<namedCache name="transactional">
  <transaction transactionMode="TRANSACTIONAL"/>
</namedCache>

transactionMode может принимать только два значения: TRANSACTIONAL и NON_TRANSACTIONAL . То же самое можно достичь и программно:

Configuration c = new Configuration();
c.fluent().transaction().transactionMode(TransactionMode.TRANSACTIONAL);
assert c.isTransactionalCache();

Важно: для транзакционных кешей необходимо настроить TransactionManagerLookup .

Обратная совместимость

AutoCommit атрибут был добавлен для того , чтобы обеспечить обратную совместимость. Если кэш является транзакционным, а
функция autoCommit включена (по умолчанию true), то любой вызов, выполняемый вне области транзакции, прозрачно переносится внутри транзакции. Другими словами, Infinispan добавляет логику для запуска транзакции перед вызовом и совершения ее после вызова.

Так что, если ваш код обращается к кэшу как транзакционен и не транзакционно, все , что вам нужно сделать при переходе на Infinispan 5.1 отметить кэш как транзакционные и включить
Autocommit (что на самом деле включено по умолчанию, так что просто не отключить его ?
Функцией autoCommit можно управлять через конфигурацию:

<namedCache name="transactional">;
  <transaction transactionMode="TRANSACTIONAL" autoCommit="true"/>
</namedCache>

или программно:

Configuration c = new Configuration();
c.fluent().transaction().autoCommit(true);
assert c.isTransactionAutoCommit();

 

Оптимистичные сделки

При оптимистических транзакциях блокировки приобретаются во время подготовки транзакции и удерживаются только до момента, когда транзакция фиксируется (или выполняется откат). Это отличается от модели блокировки по умолчанию 5.0, когда локальные блокировки получают при записи, а блокировки кластера получают во время подготовки.

Оптимистичные транзакции можно включить в файле конфигурации:

<namedCache name="transactional">
  <transaction transactionMode="TRANSACTIONAL" lockingMode="OPTIMISTIC"/>
</namedCache>

 или программно:

Configuration c = new Configuration();
c.fluent().transaction().lockingMode(LockingMode.OPTIMISTIC);
assert c.getTransactionLockingMode() == LockingMode.OPTIMISTIC;

По умолчанию транзакционный кеш оптимистичен.

Пессимистичные транзакции

С точки зрения получения блокировки, пессимистичные транзакции получают блокировки на ключах во время записи ключа. Например

transactionManager.begin();
cache.put(k1,v1); //k1 is locked
cache.remove(k2); //k2 is locked when this returns
transactionManager.commit();

Когда cache.put (k1, v1) возвращает k1, он заблокирован, и никакая другая транзакция, выполняемая где-либо в кластере, не может выполнить запись в него. Чтение к1 все еще возможно. Блокировка на k1 снимается, когда транзакция завершается (фиксация или откат).

Пессимистичные транзакции можно включить в файле конфигурации:

<namedCache name="transactional"/>
  <transaction transactionMode="TRANSACTIONAL" lockingMode="PESSIMISTIC"/>
</namedCache>

или программно:

Configuration c = new Configuration();
c.fluent().transaction().lockingMode(LockingMode. PESSIMISTIC);
assert c.getTransactionLockingMode() == LockingMode. PESSIMISTIC;

 

 

Что мне нужно — пессимистичные или оптимистичные транзакции?

С точки зрения варианта использования следует использовать оптимистичные транзакции, если между несколькими транзакциями, выполняющимися одновременно, не возникает много конфликтов. Это связано с тем, что откат оптимистичных транзакций изменился, если данные изменились между временем, когда они были прочитаны, и временем, когда они были зафиксированы (
writeSkewCheck ).

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

Путь впереди

Эта крупная доработка транзакции открыла путь для ряда других улучшений, связанных с транзакциями:

  • Модель блокировки одного узла — это важный шаг вперед во избежание взаимных блокировок и увеличении пропускной способности за счет получения блокировок только на одном узле в кластере без учета количества избыточных копий ( numOwners ), на которые реплицируются данные.
  • Переупорядочение захвата блокировки — это метод предотвращения тупиков, который будет использоваться для оптимистичных транзакций.
  • Инкрементная блокировка является еще одним методом минимизации взаимоблокировок.

С http://infinispan.blogspot.com/2011/10/transaction-remake-in-infinispan-51.html