.netsql-serverdistributed-lock

DistributedLock Acquire Order


I grabbed the NuGet package for DistributedLock for my .NET application that will be running on multiple servers. For those that do not know it makes use of SQL Server's application lock functionality to provide a simple means of locking across different machines. For what I've been using it for its been fine. However, I was wondering if the order in which the locks checked for will result in the order being maintained when the lock is released.

For example...lets say my application is reading from a queue and then processing each message in order. What if each message were about households and I wanted to process each message for a household in order. The first message encountered could use DistributedLock's Acquire to check to see if the account is free, lock it if it is free, and begin to process the message. Then lets say the queue listener app is running on another server and it reads another message from the queue for that same household. In this case Acquire would wait until the lock for the household was free and then re-lock it and process the message.

var myLock = new SystemDistributedLock("UniqueHouseholdIdentifier");

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

But what if there was a third machine running the same app and it encountered a message with the same household identifier?

So machine #1 grabs the first message for household id A01, locks it and begins to process it. Machine #2 grabs a second message on the queue for A01 and it waits. Machine #3 grabs a third message from the queue for A01 and waits.

In the case above when machine #1 is done processing it's message for A01 and frees the lock will machine #2, which picked up the second message for A01, run next before machine #3? Or will it be virtually random and either machines #2 or #3 might Acquire the next lock? Will order be maintained?


Solution

  • I present this answer with the caveat that I'm a DBA and not an application developer (I know just enough C# to be dangerous).

    Looking at the two things you've linked to, I wouldn't assume that there's any ordering to the request. sp_getapplock uses the same locking functionality that SQL uses to lock things like rows and tables. It's just that you're defining the name of a virtual resource. As such, when a task asks for a lock through sp_getapplock, the following happens (at a high level)

    The gotcha is that each scheduler has its own runnable queue (i.e. there isn't just one runnable queue per SQL instance), so which process gets there first is non-deterministic.

    If you're looking for in order processing, you may want to take a look at Service Broker or some other sort of queuing technology with topics and in-order delivery.