Как реализовать автономную блокировку записи и чтения - PullRequest
2 голосов
/ 11 февраля 2009

Некоторый контекст для вопроса

  • Все объекты в этом вопросе являются постоянными.
  • Все запросы будут поступать от клиента Silverlight, который обращается к серверу приложений по двоичному протоколу (Hessian), а не по WCF.
  • У каждого пользователя будет сеансовый ключ (не сеанс ASP.NET), который будет строкой, целым числом или GUID (пока не определено).

Для редактирования некоторых объектов может потребоваться много времени (30 или более минут), поэтому мы решили использовать пессимистическую автономную блокировку. Пессимистично, потому что необходимость согласовывать конфликты была бы слишком раздражающей для пользователей, в автономном режиме, потому что клиент не постоянно подключен к серверу.

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

public interface ILockable
{
  Guid LockID { get; }
}

Этот LockID будет идентификатором объекта "Lock", который содержит информацию о том, какой сеанс его блокирует.

Теперь, если бы это была простая пессимистическая блокировка, я смог бы добиться этого очень просто (используя увеличивающийся номер версии в Lock для выявления конфликтов обновлений), но мне действительно нужна пессимистическая автономная блокировка ReaderWriter.

Причина в том, что некоторые части приложения будут выполнять действия, которые читают эти сложные структуры. К ним относятся такие вещи, как

  • Чтение одной структуры для ее клонирования.
  • Чтение нескольких структур для создания двоичного файла для «публикации» данных во внешнем источнике.

Блокировки чтения будут удерживаться в течение очень короткого периода времени, обычно менее секунды, хотя при некоторых обстоятельствах они могут удерживаться примерно 5 секунд при предположении.

Блокировки записи в основном будут храниться в течение длительного времени, поскольку они в основном удерживаются людьми.

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

Еще одно замечание: если я хочу установить блокировку записи и есть некоторые блокировки чтения, я бы хотел поставить в очередь блокировку записи, чтобы новые блокировки чтения не устанавливались. Если блокировки чтения удаляются в течение X секунд, тогда получается блокировка записи, если нет, то блокировка записи снимается; новые блокировки чтения не будут помещены, пока блокировка записи находится в очереди.

Пока у меня есть эта идея

  1. Объект Lock будет иметь номер версии (int), поэтому я могу обнаруживать конфликты при многократном обновлении, перезагрузить, попробовать еще раз.
  2. У него будет строка [] для блокировки чтения
  3. Строка для хранения идентификатора сеанса с блокировкой записи
  4. Строка для хранения блокировки записи в очереди
  5. Возможно, счетчик рекурсии позволяет многократно блокировать один и тот же сеанс (как для блокировки чтения, так и для записи), но пока не уверен в этом.

Правила:

  • Невозможно установить блокировку чтения, если есть блокировка записи или блокировка записи в очереди.
  • Невозможно установить блокировку записи, если есть блокировка записи или блокировка записи в очереди.
  • Если блокировок вообще нет, то можно установить блокировку записи.
  • Если есть блокировки чтения, тогда блокировка записи будет поставлена ​​в очередь вместо полной блокировки записи. (Если по истечении времени X блокировки чтения не исчезают, блокировка отключается, в противном случае она обновляется).
  • Не удалось поставить в очередь блокировку записи для сеанса с блокировкой чтения.

Кто-нибудь может увидеть какие-либо проблемы? Предложить альтернативы? Что-нибудь? Буду признателен за обратную связь, прежде чем принять решение о том, какой подход выбрать.

Ответы [ 3 ]

1 голос
/ 12 февраля 2009

(отредактировано так, чтобы больше формулировать как ответ, а не как кучу вопросов)

Я ответил на это и в списке DDD Yahoo, но может и здесь для полноты.

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

За исключением этого (или даже такого), вы можете рассмотреть возможность использования метода для снятия блокировок вручную, если вы еще не учли это - в зависимости от пользователей / ролей системы, возможно, какой-то простой в использовании интерфейс администратора.

Кроме того, и вы, несомненно, тоже об этом подумали, убедитесь, что массив блокировки чтения является поточно-ориентированным.

1 голос
/ 11 февраля 2009

Рассматривали ли вы mvcc реализацию:

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

0 голосов
/ 25 февраля 2009

Если вы действительно хотите запустить собственную блокировку, я бы следовал схеме блокировки, похожей на блокировку потоков, например, в ReaderWriterLockSlim.

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

...