DistributedLock Получить заказ

Я взял пакет NuGet для DistributedLock для моего приложения.NET, которое будет работать на нескольких серверах. Для тех, кто не знает, он использует функциональность блокировки приложений SQL Server, чтобы обеспечить простые средства блокировки на разных компьютерах. За то, что я использую это для его было хорошо. Однако мне было интересно, приведет ли порядок, в котором проверяются блокировки, к порядку, который будет поддерживаться при снятии блокировки.

Например... допустим, мое приложение читает из очереди, а затем обрабатывает каждое сообщение по порядку. Что, если каждое сообщение было о домохозяйствах, и я хотел обработать каждое сообщение для домохозяйства по порядку. В первом обнаруженном сообщении можно использовать команду "Распределить блокировку", чтобы проверить, свободна ли учетная запись, заблокировать ее, если она свободна, и начать обработку сообщения. Затем предположим, что приложение прослушивателя очереди работает на другом сервере и читает другое сообщение из очереди для этого же домашнего хозяйства. В этом случае Acquire будет ждать, пока не освободится блокировка для домохозяйства, а затем повторно заблокирует ее и обработает сообщение.

var myLock = new SystemDistributedLock("UniqueHouseholdIdentifier");

using (myLock.Acquire())
{
    // message processed here in the lock
}

Но что, если на третьем компьютере было запущено то же приложение, и оно обнаружило сообщение с тем же идентификатором домохозяйства?

Таким образом, машина #1 получает первое сообщение с идентификатором домохозяйства A01, блокирует его и начинает обрабатывать. Машина #2 получает второе сообщение в очереди для A01 и ждет. Машина #3 получает третье сообщение из очереди для A01 и ждет.

В вышеприведенном случае, когда машина № 1 завершит обработку своего сообщения для A01 и освободит блокировку, машина #2, которая взяла второе сообщение для A01, будет запущена перед машиной № 3? Или это будет практически случайно, и машины № 2 или № 3 могут получить следующую блокировку? Будет ли порядок поддерживаться?

1 ответ

Решение

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

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

  • Задача переходит в рабочую очередь
  • Задача попадает в начало очереди
  • Если блокировка в данный момент не принадлежит другому процессу, вы получаете ее, и все готово
  • Если блокировка в данный момент принадлежит другому процессу, вы переходите в состояние ожидания
  • Когда блокировка снята, ваш процесс получает сигнал "проснуться", после чего он переходит в очередь, которую можно запустить (т.е. вернуться к первому шагу)

Суть в том, что у каждого планировщика есть своя работоспособная очередь (т. Е. Не существует только одной работоспособной очереди на экземпляр SQL), поэтому процесс, который туда попадает первым, является недетерминированным.

Если вы ищете для обработки заказов, вы можете взглянуть на Service Broker или какой-либо другой вид технологии очередей с темами и доставки заказа.

Другие вопросы по тегам