Distributed lock implementation scheme

1. Stand-alone mode

In this case, if we implement the lock, we can use synchronized or ReentrantLock, but in a distributed case, they can only lock the thread of the current JVM at most, and can do nothing for the threads of other servers. So how to deal with it? 

2. Distributed lock

1. Optimistic locking based on database tables

Generally, when reading out data by adding a "version" field to the database table, the version number is read out together, and then 1 is added to the version number when updating. During the update process, the version numbers are compared. If they are consistent and have not changed, the operation will be successfully executed; if the version numbers are inconsistent, the update will fail.

2. Use the add() method of memcached

This command will only add if the KEY does not exist , or will not process it. All Memcached commands are atomic, and if the same KEY is added concurrently, only one will succeed.

We need to specify the valid time of the currently added key in the use of add(). If the valid time is not specified, after executing our own business under normal circumstances, use the delete method to delete the key, which is to release the occupied resources. . However, if memecached or its own business server goes down after the place is successfully occupied, this resource will not be released. Therefore, by setting the timeout time for the key, even if there is a downtime, the resources will not be occupied all the time, and the deadlock problem can be avoided.

3. Use the setnx() and expire() methods of redis

Compared with the add() scheme of memcached(), the advantage of redis is that it supports more data types, while memcached only supports one data type of String.

The specific use steps are as follows:

  1. The setnx() method is atomic. If the key does not exist, the current key is successfully set and 1 is returned; if the current key already exists, the current key is failed to be set and 0 is returned;
  2. However, it should be noted that the setnx command cannot set the timeout time of the key, and can only be set for the key through expire();
  3. After executing the business code, use the delete command to delete the key immediately.

4. Zookeeper distributed lock

First, let's take a look at the characteristics of zookeeper and see why it is suitable for distributed locks.

  Zookeeper is a software that provides consistent services for distributed applications. It has a hierarchical file system directory tree structure inside, which stipulates that there can only be one unique file name in a unified directory.

Data model:

  • Permanent node: After the node is created, it will not disappear due to session failure

  • Ephemeral nodes: Contrary to permanent nodes, if the client connection fails, the node is immediately deleted

  • Sequential node: Similar to the above two node features, if you specify to create such a node, zk will automatically add a number suffix to the node name, and it is ordered.

  Monitor (watcher):

  • When creating a node, you can register a monitor for the node. When the node state changes and the watch is triggered, ZooKeeper will send only one notification to the client, because the watch can only be triggered once.

According to these features of zookeeper, let's take a look at how to use these features to implement distributed locks:

  1. Create a lock directory lock

  2. The thread A that wants to obtain the lock is in the lock directory and creates a temporary sequence node

  3. Get all the child nodes in the lock directory, and then get the sibling nodes smaller than yourself. If it does not exist, it means that the current thread sequence number is the smallest and the lock is obtained.

  4. Thread B obtains all nodes, judges that it is not the smallest node, and sets a watcher (watcher) to the node that is the next smaller than itself (only paying attention to the node that is the second smaller than itself is to prevent the occurrence of "herd effect")

  5. Thread A finishes processing and deletes its own node. Thread B listens to the change event, determines that it is the smallest node, and obtains the lock.

Advantages of using zookeeper

  • The lock cannot be released? Using Zookeeper can effectively solve the problem that the lock cannot be released, because when the lock is created, the client will create a temporary node in ZK. Once the client acquires the lock and suddenly hangs up (the session connection is disconnected), then this temporary node The node is automatically deleted. Other clients can then acquire the lock again.

  • Non-blocking locks? Using Zookeeper can achieve blocking locks. Clients can create sequential nodes in ZK and bind listeners to the nodes. Once the nodes change, Zookeeper will notify the client, and the client can check whether the node it created is current. The node with the smallest serial number among all nodes, if it is, then it will acquire the lock and execute the business logic.

  • Not reentrant? Using Zookeeper can also effectively solve the problem of non-reentrancy. When the client creates a node, it directly writes the host information and thread information of the current client into the node. The next time it wants to acquire the lock, it will be the smallest node at present. Compare the data in . If the information is the same as your own, then you can directly acquire the lock, if not, create a temporary sequence node to participate in the queuing.

  • Single point question? Using Zookeeper can effectively solve single-point problems. ZK is deployed in a cluster. As long as more than half of the machines in the cluster survive, it can provide external services.

 

Reference article: https://www.cnblogs.com/austinspark-jessylu/p/8043726.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325109928&siteId=291194637