From pessimistic locks, optimistic locks to distributed locks
preface
When we design goods down the module in order to prevent “inventory” oversold condition, we often use a lock mechanism and solve the problem of data consistency under the multithreading, but in the distributed cluster order node locks are often unable to meet the needs of the business, this blog since pessimistic locking, optimistic locking, gradually introduce distributed data consistency – the most effective tools for distributed lock.
The body of the
Pessimistic locks and optimistic locks
The difference between pessimistic and optimistic locks:
- Pessimistic locking: a piece of execution logic with a pessimistic lock. When different threads are executing at the same time, only one thread can execute it. The other threads wait at the entrance until the lock is released
sychronized
Pessimistic locks are provided - Optimistic lock: a piece of execution logic plus optimistic lock, when different threads execute at the same time, can enter the execution at the same time, in the last update of data to check whether the data has been modified by other threads (version and the initial execution is the same), the update, otherwise abandon this operation.
Common solutions for pessimistic and optimistic locking are:
Java
- Pessimistic locks:
synchronized
orReentrantLock
- Optimistic locking:
java.util.concurrent.atomic
The atomic variable
Mysql
- Pessimistic locks:
for update
- Optimistic lock: timestamp or
version
The version number
Redis
- Pessimistic lock: none
- Optimistic lock: use
watch
Monitor object changes to achieve optimistic locking
Zookeeper
- Pessimistic lock: none
- Optimistic lock: use
version
Version numbers implement optimistic locking
A distributed lock
Sometimes we need to ensure that a method can only be executed by the same thread at the same time. In single-machine mode, it can be implemented by sychronized, lock, etc.
Three actions for a distributed lock:
- lock
- unlock
- Lock expired
Implementation of distributed lock solutions
Database lock scheme
- Determine resource usage based on a record in a table
- Use database-based exclusive locks (i.e
select * from tb_User for update
) - The way optimistic locks are used, i.e
CAS
Actions (orversion
Field)
Redis scheme
Redis distributed locks have three behaviors:
- lockUse:
setnx
To rob the lock, set the lock identifier to 1 to indicate that the lock is occupied. - unlockUse:
setnx
To release the lock and set the lock identifier to 0 to indicate that the lock has been released. - Lock expired:
expire
Add an expiration date to the lock in case it forgets to release,expire
Time expiration returns 0.
Setnx and EXPIRE are atomic operations, and in practice lua scripts are used to ensure atomicity.
Redis can cause data inconsistency in some extreme cases:
Case 1: The master is down
redis cluster
In A clustered environment, if client A wants to lock now, it will select one based on routing rulesmaster
Node writeskey mylock
After the lock is successfully added,master
The node tokey
Asynchronously copy to correspondingslave
Node.- If at this time
redis master
When the node is down, an active/standby switchover is performed to ensure cluster availability.slave
Into theredis master
. B Client in the newmaster
The node is successfully locked, and client A thinks it is successfully locked. - In this case, multiple clients lock a distributed lock at the same time, resulting in various dirty data.
Case two: The lock expires and the business is not finished
A special scenario causes slow service processing, but the lock expires and data is modified by other threads, resulting in dirty data.
Case 3: The transaction times out because the lock is not obtained for a long time
Transaction timeout Is used to control the timeout of transaction execution. The execution time is the sum of all code executions within a transaction, in seconds. The default value is -1, which indicates that the transaction will never timeout. If the timeout period is set for some services, the transaction will be automatically rolled back if the lock cannot be obtained for a long time.
Case 4: THE lock of B is released by A
Simulation scenario:
- A, B two threads to try to give
key myLock
Thread A takes the lock first (if the lock expires after 3 seconds) and thread B waits to try to acquire the lock. - If the business logic is time consuming, the execution time has expired
redis
When the lock expires, the lock of thread A is automatically released (deleted)key
), thread B has detectedmyLock
thiskey
None, execute
SETNX
The command also got the lock. - However, thread A will still release the lock (delete) after executing the business logic
key
), which causes thread B’s lock to be released by thread A.
Solution: Each thread must be identified with its own value when locking, and only release the key of the specified value. Otherwise, the scene of chaotic lock release will occur.
Redisson scheme
Redisson is an enterprise-level open source Redis Client that also provides distributed lock support:
Redisson
All orders passedlua
Script execution, whilelua
Scripts support atomic execution;- Assuming that
Redisson
Set up akey
The default expiration time of theRedisson
“Guard dog” mechanism, it will be after you acquire the lock, every 10 seconds for youkey
In this case, the lock will not appear even if it is held all the timekey
Expired, another thread is getting the lock. Redisson
The “watchdog” logic of the “watchdog” ensures that no deadlocks occur: if the machine goes down, the watchdog is gone. It’s not going to be prolongedkey
After 30 seconds, the lock will automatically expire. Other threads can obtain the lock.
RedLock scheme
RedLock is a distributed lock algorithm implemented by multi-node Redis, which can solve the mutual exclusion failure caused by inconsistent data when the master is down under asynchronous master/slave replication in Redis sentry mode.
RedLock’s algorithm features:
- synchronous:
RedLock
Because eachredis
The time flow rate is about the same, soRedLock
You can think of it as a synchronous algorithm; - The mutex: Only one at any time
client
Acquiring a lock; - Release deadlock: The lock can be released even if the service or partition that locks the resource crashes.
- Fault tolerance: As long as most
redis
Nodes (more than half) are in use,client
Can acquire and release locks;
Suppose there are five completely independent Redis primary servers:
- Get the current timestamp;
client
Try using the same ones in orderkey
.value
Get all theredis
The lock of a service is acquired for a much shorter time than the lock expires in order not to wait too long for closed locksredis
Service. And try to get the next oneredis
Instance. Such as:TTL
As 5s, set the maximum duration of acquiring the lock to 1s. Therefore, if the lock cannot be acquired within a second, the lock will be abandoned and the next lock will be attempted.client
By taking all available locks minus the time of the first step, the time difference is less thanTTL
Time and at least threeredis
Only when the instance successfully obtains the lock, the lock is successfully obtained.- If the lock is successfully acquired, the lock’s true duration is
TTL
Subtract the time difference of step 3; Such as:TTL
Is 5s. It takes 2s to acquire all the locks, minus clock drift (which can be ignored in practice), so the actual lock duration is 3s. - If the client fails to acquire the lock for some reason, it starts unlocking everything
redis
Instance; Because less than 3 locks may have been acquired, they must be released or others will be affectedclient
Acquiring a lock;
TTL: redis key expiration time or validity time
Clock drift: Refers to the difference in time between two computers (or between two processes) when the time flow rate between two computers is basically the same; If the computer is too far away, the clock drift value will be too large
Zookeeper scheme
Zookeeper distributed lock features:
- Based on the
zookeeper
Temporary ordered nodes can achieve distributed locking. The general idea is that when each client locks a method, the value ofzookeeper
In the directory of the specified node corresponding to the method, a unique instantaneous ordered node is generated. - The way to determine whether to obtain the lock is very simple, just need to determine the smallest serial number in the ordered node. When the lock is released, the instantaneous node is simply removed.
Curator
Is azookeeper
Open source client, also provides distributed lock implementation;
The algorithm flow of distributed lock using ZooKeeper is as follows:
- If the root node of the lock space does not exist, it is created first
Znode
The root node. So let’s say that this is”/test/lock
“. This root node represents a distributed lock. - If the client needs to occupy the lock, the
/test/lock
“To create temporary and ordered child nodes. - If a client needs to occupy a lock, it also needs to check whether the child node created by the client is the child node with the smallest serial number in the current child node list. If yes, the lock is considered acquired, otherwise listen on the previous one
Znode
Child node change message, after obtaining the child node change notification, repeat this step until obtaining the lock; - Once the lock is acquired, the business process is processed. After the service process is complete, delete the child node to release the lock. So that subsequent nodes acquire distributed locks.
Differences between Redis distributed lock and Zookeeper distributed lock
redis
Distributed lock, in fact, you need to constantly try to obtain the lock, compared to consume performance;zookeeper
Distributed lock, can not obtain the lock, register a listener, do not need to constantly actively try to obtain the lock, low performance overhead;redis
The client that acquires the lockbug
The lock can only be released after the timeout period. whilezk
Because it’s temporaryznode
As soon as the client dies,znode
Then it will automatically release the lock;redis
Choice is usedRaft
Algorithm but it itself adopts asynchronous replication, so its data is not strong consistency, some extreme cases will lead to data inconsistency, but can be adoptedRedisson
Scheme,RedLock
Programmes to reduce the impact of these extremes;zookeeper
Using thePaxos
The algorithmzab
The protocol ensures strong consistency of data.