Home Java javaTutorial Java implements distributed lock based on Redis

Java implements distributed lock based on Redis

Aug 28, 2019 pm 04:12 PM
java

Distributed locks can be implemented in many ways, such as zookeeper, redis.... Either way, the basic principle remains the same: a state value is used to represent the lock, and the occupation and release of the lock are identified by the state value.

Java implements distributed lock based on Redis

1. Why Redis can easily implement distributed locks

1. Redis is a single-process single-thread mode, using queues The mode turns concurrent access into serial access, and there is no competition between multiple clients' connections to Redis.

2. Redis’s SETNX command can easily implement distributed locks.

setNX(SET if Not eXists)

Syntax: SETNX key value

Return value: If the setting is successful, 1 is returned; if the setting fails, 0 is returned.

Set the value of key to value if and only if key does not exist, and return 1; if the given key already exists, SETNX does not take any action and returns 0.

To sum up, you can use the return value of setnx to determine whether the lock is acquired, and you don’t have to worry about concurrent access, because Redis is single-threaded, so if it returns 1, the lock is acquired, and 0 is returned. It was not obtained. When the business operation is completed, the lock must be released. The logic of releasing the lock is very simple, which is to delete the previously set key, so that the lock can be obtained by setnx the key next time.

2. Distributed lock implementation

We already know that distributed locks can be implemented through Redis’s own function setNX. The specific implementation steps are as follows.

I installed the Redis service in a CentOS7 Linux virtual machine. The IP address is: 192.168.246.130 and the service port is: 6379.

The following is an example of java implementing distributed locks through redis:

import redis.clients.jedis.Jedis;
public class RedisLock {
	//锁的key
	private static final String key = "DistributedRedisLock";
	private static Integer count = 0;
	public static void main(String[] args) {
		for(int i=0;i<1000;i++){
			new Thread(new Runnable() {
				@Override
				public void run() {
					//获取Redis连接
					Jedis jedis = new Jedis("192.168.246.130", 6379);
					try{
						while(true){
							//获取锁
							if(jedis.setnx(key, Thread.currentThread().getName()) == 1){
								try{
									System.out.println("线程("+Thread.currentThread().getName()+")获取到锁,开始执行操作");
									count++;
									System.out.println(count);
									break;
								}finally{
									System.out.println("操作执行完成,释放锁");
									//操作执行完一定要释放锁,所以在finally块中执行
									jedis.del(key);
								}
							}else{
								//返回的不是1,说明已经有某个线程获取到了锁
								try {
									//等待100毫秒之后重试
									Thread.sleep(100l);
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
							}
						}
					}catch(Exception e){
						e.printStackTrace();
					}finally{
						//释放Redis连接
						jedis.disconnect();
					}
				}
			}).start();
		}
	}
}
Copy after login

The output of the above code is:

线程(Thread-320)获取到锁,开始执行操作
1
操作执行完成,释放锁
线程(Thread-463)获取到锁,开始执行操作
2
操作执行完成,释放锁
线程(Thread-997)获取到锁,开始执行操作
3
操作执行完成,释放锁
...
线程(Thread-409)获取到锁,开始执行操作
998
操作执行完成,释放锁
线程(Thread-742)获取到锁,开始执行操作
999
操作执行完成,释放锁
线程(Thread-286)获取到锁,开始执行操作
1000
操作执行完成,释放锁
Copy after login

Although the above code is in a single application with multiple threads It was tested, but even if multiple applications and multiple threads are used to acquire locks in a distributed environment, the results are still correct.

3. Solve the deadlock problem

The previous example code is just a test code, just to illustrate the principle. The example itself is very simple, so there are some ill-considered aspects. . For example, after acquiring the lock, an environmental problem occurs during the execution of the business operation and the connection to Redis is disconnected. Then the lock cannot be released in the finally block, causing other threads waiting to acquire the lock to wait indefinitely, which is what happens. Deadlock phenomenon.

Solution:

You can set an expiration time for the lock in Redis, so that even if the lock cannot be released, the lock can be automatically released after a period of time.

In terms of code, you only need to add the following code to the try statement block after acquiring the lock:

jedis.expire(key, 10); //这里给锁设置10秒的过期时间
Copy after login

A better solution:

One solution is not very good, because when the business operation processing time is very long and exceeds the set expiration time, the lock is automatically released, and then when the operation of releasing the lock in the finally block is executed, the lock may have been used by other users. The lock held by a thread will cause the lock held by other threads to be released, thus causing concurrency problems. Therefore, a more appropriate way is to determine whether the lock has expired when releasing the lock. If it has expired, there is no need to release it again.

In the code, change the operation after acquiring the lock to the following code:

long start = System.currentTimeMillis(); //获取起始时间毫秒数
try{
  jedis.expire(key, 10);
  ...
}finally{
  ...
  if(System.currentTimeMillis() < start+10*1000){
     //如果之前设置的锁还未过期,则释放掉
     jedis.del(key);
  }
}
Copy after login

The above is the detailed content of Java implements distributed lock based on Redis. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Perfect Number in Java Perfect Number in Java Aug 30, 2024 pm 04:28 PM

Guide to Perfect Number in Java. Here we discuss the Definition, How to check Perfect number in Java?, examples with code implementation.

Weka in Java Weka in Java Aug 30, 2024 pm 04:28 PM

Guide to Weka in Java. Here we discuss the Introduction, how to use weka java, the type of platform, and advantages with examples.

Smith Number in Java Smith Number in Java Aug 30, 2024 pm 04:28 PM

Guide to Smith Number in Java. Here we discuss the Definition, How to check smith number in Java? example with code implementation.

Java Spring Interview Questions Java Spring Interview Questions Aug 30, 2024 pm 04:29 PM

In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

Break or return from Java 8 stream forEach? Break or return from Java 8 stream forEach? Feb 07, 2025 pm 12:09 PM

Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

TimeStamp to Date in Java TimeStamp to Date in Java Aug 30, 2024 pm 04:28 PM

Guide to TimeStamp to Date in Java. Here we also discuss the introduction and how to convert timestamp to date in java along with examples.

Java Program to Find the Volume of Capsule Java Program to Find the Volume of Capsule Feb 07, 2025 am 11:37 AM

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

Create the Future: Java Programming for Absolute Beginners Create the Future: Java Programming for Absolute Beginners Oct 13, 2024 pm 01:32 PM

Java is a popular programming language that can be learned by both beginners and experienced developers. This tutorial starts with basic concepts and progresses through advanced topics. After installing the Java Development Kit, you can practice programming by creating a simple "Hello, World!" program. After you understand the code, use the command prompt to compile and run the program, and "Hello, World!" will be output on the console. Learning Java starts your programming journey, and as your mastery deepens, you can create more complex applications.

See all articles