Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement Redis distributed Lock and what is its Application scenario

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces the relevant knowledge of "how to implement Redis distributed locks and what is the application scenario". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Introduction

Lock is a very common tool in the development process, you must be no stranger, pessimistic lock, optimistic lock, exclusive lock, fair lock, unfair lock and so on, many concepts, if you do not understand the lock in java, you can refer to this article: the Java "lock", this article is very comprehensive, but for beginners, know the concept of these locks, due to the lack of practical work experience May not understand the actual use of locks, Java can use the Volatile, Synchronized, ReentrantLock three keywords to achieve thread safety, this part of the knowledge will be asked in the first round of basic interview (to be proficient in oh).

In the distributed system, Java lock technology can not lock the code on two machines at the same time, so it should be realized through distributed lock. Proficient in the use of distributed lock is also a necessary skill for large manufacturers to develop.

1. Interviewer: have you come across any scenarios where you need to use distributed locks?

Problem analysis: this problem is mainly used as an introduction. First, we need to understand what scenarios need to use distributed locks and what problems distributed locks need to solve. Under this premise, it will help you to better understand the implementation principle of distributed locks.

Scenarios that use distributed locks generally need to meet the following scenarios:

The system is a distributed system and the lock of java can no longer be locked.

Manipulate shared resources, such as unique user data in the library.

Synchronous access, that is, multiple processes operate shared resources at the same time.

A: give me an example of a scenario where I used distributed locks in a project:

Consumer points are available in many systems, such as credit cards, e-commerce websites, exchanging points for gifts, etc., where the operation of "consumer points" is a typical scenario where locks are needed.

Event A:

Taking the exchange of points for gifts as an example, the complete process of points consumption is simply divided into three steps:

A1: the user selects the item and initiates the exchange to submit the order.

A2: the system reads the user's remaining points: judge whether the user's current points are sufficient.

A3: deduct user points.

Event B:

The system to issue points to users is also simply divided into three steps:

B1: calculate the points due to the user on the same day

B2: read the user's original points

B3: add the due points to the original points

So the question is, what if user consumption credits and user cumulative credits occur at the same time (and user credits operate at the same time)?

Suppose: when the user consumes the points, the offline task happens to calculate the points and issue the points to the user (for example, according to the amount of consumption of the user on the day), these two things are carried out at the same time, the following logic is a little roundabout, patient understanding.

User U has 1000 points (the data recording user points can be understood as shared resources). This exchange will consume 999 points.

Unlocked situation: event A program in the implementation of the second step to read the points, the result is 1000 points, judging that the remaining points are enough for this exchange, followed by the third step to perform the points (1000-999 = 1), the normal result should be the user or 1 point. But event B is also executing at this time. This time, 100 points will be issued to user U, and the two threads will access synchronously and unlocked, there will be the following possibility: av 2-> BRV 2-> ARV 3-> BRV 3. Before ARV 3 is completed (deduction points, 1000-999), the total score of user U is read by the thread of event B, and finally the total score of user U becomes 1100 points. Also exchanged for a gift of 999 points for nothing, which is obviously not in line with the expected results.

Some people say that how is it possible to operate user points at the same time? cpu is so fast, as long as there are enough users and the concurrency is large enough, Murphy's law will come into effect sooner or later, it is only a matter of time before the above bug appears, and it may also be stuck by the underground industry. At this time, developers must understand the use of locks if they want to solve this hidden danger.

Writing code is a serious thing! )

Java itself provides two built-in lock implementations, one is Lock provided by synchronized and JDK implemented by JVM, and many atomic operation classes are thread-safe. When your application is a stand-alone or single-process application, you can use these two locks to implement locks.

But at present, almost all the systems of Internet companies are distributed, at this time, the synchronized or Lock included in Java can no longer meet the requirements of locking in a distributed environment, because the code will be deployed on multiple machines. In order to solve this problem, distributed locks emerge as the times require. Distributed locks are characterized by multiple processes and multiple physical machines cannot share memory. The common solution is based on the interference of the memory layer. The landing scheme is based on Redis distributed lock or ZooKeeper distributed lock.

My analysis can not be more detailed, the interviewer is no longer satisfied? )

2. Interviewer: Redis distributed lock implementation method

Problem analysis: at present, there are two main ways to realize distributed lock, 1. Based on Redis Cluster mode. two。 Based on Zookeeper cluster mode.

If you give priority to these two kinds, you will have no problem dealing with the interview.

A:

1. Distributed lock based on Redis.

Method 1: use the setnx command to add locks

Public static void wrongGetLock1 (Jedis jedis, String lockKey, String requestId, int expireTime) {/ / first step: lock Long result = jedis.setnx (lockKey, requestId); if (result = = 1) {/ / second step: set the expiration time jedis.expire (lockKey, expireTime);}}

Code interpretation:

The setnx command, which means set if not exist, stores the key in Redis if lockKey does not exist. If result returns 1 after saving successfully, it means the setting is successful. If it is not 1, it means failure, and other threads have already set it.

Expire (), set the expiration time to prevent deadlocks, assuming that if a lock is not deleted after set, then the lock is equivalent to existing all the time, resulting in a deadlock.

(at this point, I would like to emphasize a "but" with the interviewer.)

Thinking, what are the defects of my above method? Continue to explain to the interviewer...

Locking is divided into two steps, the first step jedis.setnx, the second step jedis.expire set expiration time, setnx and expire is not an atomic operation, if the program after the first step is abnormal, the second step jedis.expire (lockKey, expireTime) has not been executed, equivalent to the lock has no expiration time, there is the possibility of deadlock. How to improve this problem?

Improvements:

Public class RedisLockDemo {private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX" / * * acquire distributed lock * @ param jedis Redis client * @ param lockKey lock * @ param requestId request identification * @ param expireTime expiration time * @ return whether the acquisition was successful * / public static boolean getLock (Jedis jedis, String lockKey, String requestId, int expireTime) {/ / the two steps are merged into one One line of code locks and sets the + expiration time. If (1 = = jedis.set (lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime)) {return true;// lock success} return false;// lock failure}

Code interpretation:

Lock and set the expiration time into one, one line of code, atomic operation.

(without waiting for the interviewer to ask questions, the interviewer is satisfied.)

Interviewer: what about the unlocking operation?

A:

To release the lock is to delete the key

Use the del command to unlock public static void unLock (Jedis jedis, String lockKey, String requestId) {/ / step 1: use requestId to determine whether locking and unlocking are the same client if (requestId.equals (jedis.get (lockKey) {/ / step 2: if the lock suddenly does not belong to this client at this time, the lock jedis.del (lockKey) will be misunderstood;}}

Code interpretation: through requestId to determine whether locking and unlocking is the same client and jedis.del (lockKey) two steps are not atomic operations, in theory will appear after the implementation of the first step if judgment operation actually expired, and was acquired by other threads, this is the time to perform jedis.del (lockKey) operation, equivalent to the release of other people's lock, which is unreasonable. Of course, this is a very extreme situation. If there are no other business operations in the first and second steps of the unLock method, and the above code is thrown online, there may not be a real problem. The first reason is that the number of business concurrency is not high and this defect will not be exposed at all, then the problem is not big.

But writing code is a rigorous job, and it must be perfect to be perfect. Aiming at the problems in the above code, this paper puts forward some improvements.

Code improvements:

Public class RedisTool {private static final Long RELEASE_SUCCESS = 1L / * * release distributed lock * @ param jedis Redis client * @ param lockKey lock * @ param requestId request to identify whether @ return has been released successfully * / public static boolean releaseDistributedLock (Jedis jedis, String lockKey, String requestId) {String script = "if redis.call ('get', KEYS [1]) = ARGV [1] then return redis.call (' del') KEYS [1]) else return 0 end " Object result = jedis.eval (script, Collections.singletonList (lockKey), Collections.singletonList (requestId)); if (RELEASE_SUCCESS.equals (result)) {return true;} return false;}}

Code interpretation:

The atomic problem in method one is solved through the eval method of the jedis client and one line of code of the script script.

3. Interviewer: the implementation principle of distributed lock based on ZooKeeper

A: or an example of integral consumption and integral accumulation: event An and event B need to modify the integral at the same time, two machines at the same time, the correct business logic allows one machine to execute first and then another machine to execute, either event An executes first, or event B executes first. Only in this way can we make sure that there will not be more and more points such as bug 2-> BRV 2-> BRV 3-> BRV 3. (I may cry when I think that once the bug is online, the boss will be angry.)

What shall I do? Use zookeeper distributed locks.

After one machine receives the request, it first acquires a distributed lock on the zookeeper (zk creates a znode) and performs the operation; then another machine also tries to create that znode, only to find that it cannot create it, because it has been created by someone else, so it can only wait until the first machine finishes executing the lock.

Using the sequential node feature of ZooKeeper, if we create three nodes under the / lock/ directory, the ZK cluster will create nodes in the order in which they are initiated. The nodes are divided into / lock/0000000001, / lock/0000000002, / lock/0000000003. The last digit is incremented in turn, and the node name is completed by zk.

There is also a node in ZK called a temporary node, which is created by a client and is automatically deleted when the client is disconnected from the ZK cluster. EPHEMERAL_SEQUENTIAL is a temporary sequential node.

According to whether a node exists in ZK, it can be used as the lock state of a distributed lock to implement a distributed lock. The following is the basic logic of distributed lock:

The client calls the create () method to create a temporary sequential node named "/ dlm-locks/lockname/lock-".

The client calls the getChildren ("lockname") method to get all the child nodes that have been created.

After the client acquires all the child nodes path, if it finds that the node it created in step 1 has the lowest sequence number of all nodes, it will see if the sequence number it creates ranks first. If it is the first, then the client will be considered to have acquired the lock, and no other client will get the lock in front of it.

If the node created is not the smallest of all nodes, then monitor the largest node that is smaller than the sequence number of the node you created, and enter the wait. Until the next time the monitored child node changes, the child node is acquired to determine whether to acquire the lock or not.

The process of releasing the lock is relatively simple, which is to delete the child node you created, but you still need to consider exceptions such as the failure to delete the node.

Additional supplement

Distributed locks can also solve problems from the database.

Method 1:

Using the lock table of Mysql, create a table and set a UNIQUE KEY this KEY is the KEY to be locked, so the same KEY can only be inserted once in the mysql table, so the competition for locks is left to the database. Dealing with the same KEY database ensures that only one node can be inserted successfully, and all other nodes will fail.

So the idea of lock and unlock is simple, pseudocode:

Def lock: exec sql: insert into locked-table (xxx) values (xxx) if result = = true: return true else: return falsedef unlock: exec sql: delete from lockedOrder where order_id='order_id' method 2:

Using the serial number + timestamp for idempotent operations can be seen as a lock that will not be released.

This is the end of the content of "how to implement Redis distributed locks and what is the application scenario". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report