Distributed Lock in MicroServices
Distributed locking is a technique to manage many applications or instances of applications that try to access the same resource. The primary purpose is to allow only one of many applications to access the same resource simultaneously.
The Problem
In Software Engineering, there are scenarios when we want to place a mutex lock in some section of code before executing that section and want no other application can access that code while some service is still in that critical section. There are many scenarios in which distributed locks can help us
Suppose there is a microservice with 3 pods named A, B, and C and a scheduled cron job that runs every day at 12:00 AM for some routine task. Because this cron job is written inside the microservice so always 3 instances of the cron job will run at 12:00 AM every day. This will cause unnecessary complexity and may corrupt data of routine tasks. So where we can place distributed mutex lock so only one pod can execute this routine task while for other pods this section of code is locked for execution.
Redlock
If your software uses Redis then you can use Redlock distributed lock, an Algorithm proposed by Redis. This Algorithm implementation is already available in different programming languages. you can read more about it on the official site.
Sample implementation in Javascript
// Creating Redlock instance for some key with help of any library implementation.
const mutex = new RedLock("keyToLock")
// trying to acquire lock if it is available to acquire.
const isLockAcquired = await mutex.tryAcquire();
// if lock is acquired successfully the execute critical code.
if (isLockAcquired){
scheduleTask()
// once task is done, release lock for key
await mutex.release()
} else{
console.log("task is already running in some other pod.")
}
Postgres Advisory Locks
Postgres Advisory Locks are a great solution for arbitrary application locks, particularly in scenarios where you are already using Postgres and have a need to block concurrent mutations to a resource (that resource DOES NOT have to be data in Postgres).
There are two types of Postgres Advisory Locks: session and transaction.
Session Locks: Session locks, once acquired, are held until they are manually released or the database client is disconnected:
-- Acquire a lock using an arbitrary BigInt.
-- if fails to acquire a lock, an error will be returned to the client.
SELECT pg_advisory_lock(123);
-- Unlock
SELECT pg_advisory_unlock(123);
-- return "true" is the lock is acquired, "false" if not.
SELECT pg_try_advisory_lock(123);
Transaction Locks: Transactions locks differ only in that they are released at the end of a transaction. Transaction Advisory Locks differ only in _xact
on function names:
SELECT pg_advisory_xact_lock(123);
SELECT pg_advisory_xact_unlock(123);
SELECT pg_try_advisory_xact_lock(123);
Hope this helps! Let me know if you have any other questions.