0 4.1K ru

Offline Concurrency паттерны из PoEAA

В этой статье рассмотрим паттерны локальной конкуренции из списка шаблонов Архитектуры корпоративных программных приложений (PoEAA).

Оптимистическая блокировка (Optimistic Offline Lock)

Оптимистическая блокировка - предотвращает возникновение конфликтов между параллельными бизнес-транзакциями путем обнаружения конфликта и отката транзакции.

optimistic lock


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

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

Как реализовать оптимистическую блокировку?

Вы можете реализовать оптимистическую блокировку множеством способов, но фундамент для реализации оптимистической блокировки остается прежним. Алгоритм рассписан ниже:

  1. Записать текущий timestamp времени.
  2. Начните изменять значения.
  3. Перед обновлением проверьте, изменил ли кто-либо значения, проверив старый timestamp в базе (который мы записали на шаге 1) и ваш timestamp в коде.
  4. Если они не равные делаем rollback или коммит если они совпали.
optimistic lock

Пессимистическая блокировка (Pessimistic Offline Lock)

Пессимистическая блокировка - предотвращает возникновение конфликтов между параллельными бизнес-транзакциями, предоставляя доступ к данным в конкретный момент времени только одной бизнес-транзакции.

pessimistic offline lock

 

Пессимистическая блокировка реализуется в три этапа: определение необходимого типа блокировок, построение диспетчера блокировки и составление правил применения блокировок. Кроме того, если пессимистическая блокировка используется в качестве дополнения к оптимистической блокировке, понадобится определить типы записей, которые необходимо блокировать.

Первый возможный тип блокировки — это монопольная блокировка записи (exclusive write lock), которая требует наложения блокировки только для редактирования данных. Это дает возможность избежать конфликта, не позволяя двум бизнес-транзакциям одновременно вносить изменения в одну и ту же строку. Данная схема блокирования полностью игнорирует операции чтения, поэтому вполне подходит в том случае, если параллельный сеанс допускает считывание несколько устаревших данных.

Если бизнес-транзакции обязательно нужны самые свежие данные вне зависимости от того, собирается она их редактировать или нет, используйте монопольную блокировку чтения (exclusive read lock).Разумеется, применение подобной стратегии жестко ограничивает возможность параллельного доступа к данным. В большинстве корпоративных систем монопольная блокировка записи обеспечивает более высокую степень параллелизма, чем монопольная блокировка чтения.

Третья стратегия сочетает в себе первые два типа блокировки, что ведет к жесткому ограничению доступа, свойственному монопольной блокировке чтения, и одновременному повышению степени параллелизма системы, присущему монопольной блокировке записи. Она называется блокировкой чтения/записи (read/write lock) и имеет немного более сложную схему, чем первые два типа. Данная схема подразумевает определенные отношения между блокировками чтения и записи.

  • Блокировки чтения и записи являются взаимоисключающими. Строка базы дан ных не может быть заблокирована для записи, если другая бизнес-транзакция уже заблокировала ее для чтения. Точно так же строка не может быть заблокирована для чтения, если другая бизнес-транзакция уже установила блокировку на запись.
  • Допускаются параллельные блокировки чтения. Наличие хотя бы одной блоки ровки чтения делает невозможным редактирование строки всеми другими бизнестранзакциями, поэтому выполнение других параллельных процессов, просматри вающих эту строку, вреда не принесет.

Грубая блокировка (Coarse Grained Lock)

Coarse Grained Lock- блокирует группу взаимосвязанных объектов как единый элемент.

Coarse Grained Lock

Довольно часто объекты приходится редактировать в составе группы. Предположим, у вас есть объект покупателя и множество его адресов. В этом случае при необходимости блокировки одного из элементов имеет смысл заблокировать и все остальные. Между тем применение к каждому объекту отдельной блокировки связано с определенными проблемами. Во-первых, разработчику придется писать код, который бы обнаруживал все объекты группы, чтобы их заблокировать. Это не слишком сложно для покупателя и его адресов, однако при наличии большего количества групп блокировки реализация подобного механизма может стать затруднительной. А что, если группы будут иметь более сложную структуру? Если стратегия блокирования подразумевает, что для наложения блокировки объект должен быть загружен (принцип оптимистической автономной блокировки (Optimistic Offline Lock)), блокирование большой группы объектов значительно снизит производительность. В свою очередь, при использовании пессимистической автономной блокировки (Pessimistic Online Lock) наличие большой группы объектов крайне запутывает управление блокировками и повышает конкуренцию за получение доступа к таблице блокировки.

Неявная блокировка (Implicit Lock)

Позволяет коду фреймворка или супертипа уровня использовать локальные блокировки

Implicit Lock

Суть всех блокировок в том, что при их использовании нельзя делать исключений. Если забыть написать одну строку кода, которая вызывает блокировку, можно придти к полной бесполезности всей блокировочной схемы. Не вызвав блокировку на чтение, даже если остальные транзакции её используют, можно поставить под вопрос актуальность данных. В целом - если что-то может быть заблокировано где-то, оно должно блокироваться везде. Игнорируя это правило, блокировочные стратегии приложений рискуют целостностью данных. Если не завершить блокировку вовремя, то с данными ничего плохого не случится, однако, это приведёт к провалу производительности. Из-за сложности тестирования локальных блокировок, такие ошибки могут пройти все тесты и не быть обнаруженными.

Единственное решение здесь - не дать разработчикам ошибиться. Задачи, использующие блокировки, которые не могут быть невыявленными, должны быть обработаны не явно для разработчика, но скрыто для приложения. А тот факт, что большинство приложений промышленного масштаба используют нектотрый набор фреймворков, Layer Supertype и генерацию кода, даёт большие возможности для внедрения паттерна Implicit Lock.

Comments:

Please log in to be able add comments.