Business Scenarios
Multiple concurrent requests modify the same data at the same time, for example, multiple salespersons modify the same customer's information concurrently. Modifying the same data at the same time will cause concurrent conflicts, which may lead to incorrect data and have an unpredictable impact on the business. Currently, many large websites and applications are deployed in a distributed manner, and the issue of data consistency in distributed scenarios has always been a major topic.
Solutions
Distributed locks can be implemented based on the database, but the problem is insufficient performance and cannot meet the high concurrency scenarios for large applications. Implementing distributed locks based on cache (Redis, etc.) brings significant performance advantages.
The principle of implementing distributed locks with Redis is based on: There is a command to determine whether a key exists, and a mechanism for the key to set ttl to prevent deadlock.
Here is a simple implementation idea:
(1) When acquiring a lock, use setnx to implement lock acquisition, and use the expire command to add a timeout to the lock. If the time has passed, the lock will be automatically released. The value of the lock is a randomly generated UUID. Through this, the lock is determined whether to be released.
(2) When acquiring the lock, a timeout period is also set for acquisition. If this time has passed, the acquisition of the lock fails.
(3) When releasing a lock, use the UUID to determine whether it is the lock. If it is the lock, run the delete command to release the lock.
Since there are already many mature open-source solutions, the following is a distributed lock implemented based on redisson (an open-source JAVA redis library). See this document: https://github.com/redisson/redisson/wiki/8.-Distributed-locks-and-synchronizers.
maven:
Sample Code
RLock lock = redisson.getLock("myLock");
// traditional lock method
lock.lock();
// or acquire lock and automatically unlock it after 10 seconds
lock.lock(10, TimeUnit.SECONDS);
// or wait for lock acquisition up to 100 seconds
// and automatically unlock it after 10 seconds
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
try {
...
} finally {
lock.unlock();
}
}