First, use scenarios

  1. The system is a distributed system, or cluster system, and the Java lock is no longer locked.
  2. Manipulating shared resources, such as unique user data in the library.
  3. Synchronous access means that multiple threads operate on shared resources (files, networks) simultaneously.

Second, solutions

(1) Based on Redis

introduce

Distributed locks based on Redis refer to extended development based on Redis. The main implementation is to use Redis commands: setnx key value ex 10s, Redisson, and Watch Dog (guard dog to prevent the Redis lock from being released before the program finishes executing).

The SETNX command is an abbreviation of set if not exists. Its format is: SETNX key value Sets the value of the key to value if and only if the key does not exist. If the given key already exists, setnx does nothing, and the operation fails.

  • Lock:set key value nx ex 10s
  • Release the lock:delete key

Deadlock situations and solutions

  1. The lock is not released after being locked, for exampledelete key.
  2. The program has not released the lock after the lock, the program hangs: need to use redis key expiration mechanism.

Specific use mode

Suppose there are two services A and B that want to acquire locks. The process is as follows:

  1. To obtain the lock, service A sends the following command to Redis: SET productId:lock 0xx9p03001 NX EX 30000. ProductId can be A self-defined ID related to the service. Value is A series of random values that must be globally unique. NX refers to success if and only if the key does not exist in Redis, otherwise execution fails. EX 30000 indicates that the key will be automatically deleted after 30 seconds. If the command is executed successfully, the service successfully obtains the lock.

  2. To obtain the lock, service B wants Redis to run the SET productId:lock 0000111 NX EX 30000 command. The command fails to be executed because a key with the same name already exists in the Redis memory and has not expired. Therefore, service B cannot obtain the lock. Service B enters a circular wait state, such as making a request to Redis every 1 second (self-set) until the execution succeeds and the lock is acquired.

  3. Redis automatically deletes the key. In this case, service B sends the command successfully. Assume that the value in the request is 0000111. In this case, service A needs to renew the key using watch Dog.

  4. After service A completes execution, service A initiates A request to Redis to delete the key to release the lock. Note that before deleting the key, you must determine whether the value held by service A is the same as the value stored in Redis. For example, in the current scenario, the lock of Redis is not the one held by service A, but created by service 2. If the key held by service A is used to delete the lock, the lock of service B will be released by mistake. In addition, because lock deletion involves a series of judgment logic, lua scripts are generally used, as follows:

if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
else
    return 0
end
Copy the code

(2) Based on Zookeeper

Based on the Zookeeper. According to the sequential node, temporary node features.

introduce

  • Sequential node features:

Using Zookeeper’s sequential node feature, if we create three nodes in the /lock/ directory, the ZK cluster will create the nodes in the order in which they were initiated. The nodes are /lock/0000000001, /lock/0000000002, /lock/0000000003, the last bit is incremental, and the node name is done by ZK.

  • Temporary node features:

A temporary node is created by a client and is automatically deleted when the client disconnects from the ZK cluster.

The specific implementation

  1. Called by client Acreate()Method created with the name/ ID/lock - businessTemporary order node of.
  2. Called by client AGetChildren (" ID "of business)Method to get all child nodes that have been created.
  3. The client obtains all child nodespathThen, if you find that the node you created in Step 1 has the smallest sequence number of all nodes, you can see if the sequence number you created is the first one. If the first one thinks this client has the lock, no other client has the lock before it.
  4. If the created node does not have the smallest serial number among all nodes, then monitor the node whose serial number is smaller than that of the created node and wait. Until the next time the monitored child node changes, the node is acquired to determine whether the lock is acquired.

(3) Differences between Redis and Zookeeper

  • Redis:
  1. Between Redis only guarantee eventual consistency, copy the data replication is asynchronous (Set is written, the Get is read, Redis cluster separation architecture is generally, speaking, reading and writing, and the presence of master-slave synchronization delay), in the wake of the master-slave switch there may be some data is not copy the past, lost lock 】 【 so emphasize the consistency requirements of the business is not recommended to use Redis, ZK is recommended.
  2. The response time of all methods in Redis cluster is the lowest. With the increase of concurrency and service quantity, the response speed will increase obviously (the influence factor of public network cluster is relatively large), but the limit QPS(throughput) can reach the maximum and there is almost no exception.
  • Zookeeper:
  1. In the Zookeeper cluster, the locking principle is to use the temporary sequence node of Zookeeper. The life cycle of the temporary sequence node ends when the session between the client and the cluster ends. Therefore, if a client node is disconnected from Zookeeper due to network problems, the session timeout will also cause the lock to be released incorrectly (causing the lock to be held incorrectly by other threads). Therefore, Zookeeper cannot guarantee complete consistency.
  2. ZK has good stability: the response time jitter is very small, and no abnormality occurs. However, as the number of concurrent and business increases, the response time and QPS decrease significantly. To ensure consistency, it takes time for Zookeeper to synchronize nodes.
  • Conclusion:
  1. Before each Zookeeper lock operation, several nodes are created and released, which wastes a lot of time.
  2. Redis is just a simple data operation without the above problems.

(3) Based on database

Based on databases, such as MySQL. Uniqueness of a primary key or unique index.

Insert a KEY into a MySQL table only once; insert a KEY into a MySQL table only once; insert a KEY into a MySQL table only once; insert a KEY into a MySQL table only once.

DB distributed lock implementation: Lock by the uniqueness of the primary key ID or unique index. In plain English, lock is in the form of inserting a data into a table, the id of the data is a distributed lock. For example, when a request inserts a data with id 1, Other requests that want to insert data must delete the data with ID 1 after the execution of the first request before they can continue to insert, realizing the function of distributed lock.

Lock and unlock are simple, and the pseudo-code is as follows:

def lock:
    exec sql: insert into table (`order_id`) values (xxx)
    if result == true:
        return true
    else:
        retrun false
        
def unlock:
    exec sql: delete from table where `order_id` = 'xxx'
Copy the code