In a system, sometimes you must lock a resource. This might be to make critical modifications that cannot be resolved in any concurrent way. The goals for locks are:
- One worker (and only one) worked to be able to acquire rights to a resource
- Be able to release this lock reliably
- Not deadlock any resource meaning that a resource should be unlocked after a given time period.
Redis is a good option locking since has a simple key-based data model, each shard is single-threaded, and is quite quick. There is a well-established, canonical implementations of locking using Redis called Redlock.
Redlock clients are available in almost every used language, so it is not relevant to re-invent that wheel. It is important to understand, however, how Redlock works to be able to use it safely and effectively.
First, it’s important to understand that Redlock is designed to be operated over a minimum of 3 machines with independent Redis instances. This avoids any single-point of failure in your locking mechanism (which would be a deadlock on all resources!). The other point to understand is that, while the clocks do not need to be 100% synchronized, the clocks do need to function in the same way – e.g. time moves at precisely the same pace – 1 second on machine A is the same as 1 second on machine B.
Setting a lock with Redlock starts with getting time timestamp to millisecond precision, you also must have a predetermined lock time. Then the lock is placed by SETing a key with a random value (only if the key doesn’t already exist) and also putting a timeout on the key. This is repeated for every independent instance in series. If an instance is down, then move on immediately. If the lock is successfully set in a majority of the instances before the given timeout, then lock is acquired. If it was not acquired in time then no lock is achieved. The lock time to operate on or renew the lock is the amount of time required to achieve the lock minus the total predetermined lock time. In the case of a failure or timeout, unlock all the instances and try again.
To release the lock, a Lua script is employed to check if the key set has the expected random value. If it does then you can delete the key, if not then leave it alone as it might be a newer lock.
Redlock process provides good guarantees and no single point of failure, so you can be highly confident that single locks will be doled out and that no deadlocks will occur.