Skip to content

aliostad/aws-distributed-mutex

Repository files navigation

NuGet version Build status

A distributed lock (mutex) implementation for AWS using DynamoDB. It supports .NET 4.6.1+ and .NET Standard 2.0.

Background

Locking a resource is the typical solution to synchronise parallel processes. The locking can occure for actors in the same process (critical section or lock statement in C#), across processes on the same machine (machine-wide mutex and semaphore), across different nodes on the same network (historically implemented as file locking such as Google's Chubby) or completely distributed be it on the same cloud region or across continents - which is our topic here.

In distributed locking, the phrase lease is used more often since the locking almost always is associated with a timeout. In distributed computing, all components are deemed to fail or become unavailable at some point hence by having a timout, the risk of locking a resource indefinitely due to the holder going AWOL is eliminated. Safe timeout depends on the scenarios but usually are somewhere between 30 seconds and 5 minutes. If longer duration of lease is needed, it is advised that the holders acquire a shorter lease but renew while they still need the lease longer than original timeout.

The use case is mainly scheduling a process/job across multiple consumers where there could be many consumers yet only one should be allowed to schedule the work at any time.

In Azure, we can use lease feature of the Blob Storage to build a distributed mutex. Unfortunately Amazon S3 does not provide a similar feature hence the feature must be built using general features of DynamoDB.

Usage

Create a DynamoDB table

Create a table named __lock__ (or any other name as long as you pass the name using settings object) with resourceId as the key. You may choose to enable TTL for old locks to disappear.

You can also pass a settings object with option to create the table if it does not exist, so this is done in the code.

Add a reference to the package

Install-Package AwsDistributedMutex -Version 1.x.x

Create a Mutex

If you have configured your Access Key and ID in the config or Environment Variables:

var mutex = new DynamoDBMutex(RegionEndpoint.EUWest1);

Otherwise create a client using your method of choice and pass it in to the constructor:

var client = ... // create a client
var mutex = new DynamoDBMutex(client);

Lock/Lease a resource

The resourceId string can be anything - essentially is application dependent and as for this library, as long as resource IDs have a one to one relationship with the actual resources, it is fine.

var token = await mutex.AcquireLockAsync("myid", TimeSpan.FromMinutes(1));

If token is null, then it measn the operation was not successful, otherwise a token is returned. The token can be used to renew or release the lock (lease). If none happens, it will timeout although the physical record will stay. When you create the DynamoDB table, you can opt for TTL to clear up old leases.

Release or Renew the lease

It is important to release the lock as long as the work is done

await mutex.ReleaseLockAsync(token);

For renewing, pass the original token again to renew for the intended duration. If it is successful, you will reveive another token otherwise return value will be null:

var newToken = mutex.RenewAsync(token, TimeSpan.FromMinutes(1));

About

A distributed lock (mutex) implementation for AWS using DynamoDB

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published