分布式锁,就是控制分布式系统中不同进程共同访问同一共享资源的一种锁的实现。
1、引入依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.15.5</version>
</dependency>
2、配置文件
spring:
data:
redis:
database: 1
host: localhost
port: 6379
password: *********
3、配置类
package com.example.springboot3test.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author DeyouKong
* @description TODO
* @date 2023/3/23 23:34
*/
@Configuration
public class RedissonConfig {
@Value(value = "${spring.data.redis.host}")
private String host;
@Value(value = "${spring.data.redis.port}")
private int port;
@Value(value = "${spring.data.redis.database}")
private int database;
@Value(value = "${spring.data.redis.password}")
private String password;
/**
* 单Redis节点模式配置方法
* 其他配置參數,看:
* <a href = "https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95#26-%E5%8D%95redis%E8%8A%82%E7%82%B9%E6%A8%A1%E5%BC%8F">
* 单Redis节点模式配置方法
* </a>
*
* @return {@link RedissonClient}
*/
@Bean(destroyMethod = "shutdown")
RedissonClient redisson() {
Config config = new Config();
//Redis多节点
// config.useClusterServers()
// .addNodeAddress("redis://127.0.0.1:6379", "redis://127.0.0.1:7001");
//Redis单节点
SingleServerConfig singleServerConfig = config.useSingleServer();
//可以用"rediss://"来启用SSL连接
String address = "redis://" + host + ":" + port;
singleServerConfig.setAddress(address);
//设置 数据库编号
singleServerConfig.setDatabase(database);
singleServerConfig.setPassword(password);
//连接池大小:默认值:64
// singleServerConfig.setConnectionPoolSize()
return Redisson.create(config);
}
}
4、测试代码
package com.example.springboot3test.controller;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/redission")
public class RedissionController {
@Resource
private RedissonClient redissonClient;
private final static String LOCK="I_AM_LOCK";
@GetMapping("/list")
public String getString(){
// 1、获取一把锁,只要锁的名字一样,既是同一把锁
RLock lock = redissonClient.getLock(LOCK);
// 2、加锁
//lock.lock(5, TimeUnit.SECONDS); // 阻塞式等待
if(lock.isLocked()){
//如果存在锁,则返回失败
return "fail";
}
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+":\t 获得锁");
Thread.sleep(20000);
} catch (Exception e) {
e.printStackTrace();
return "占用所";
}finally {
// 3、解锁
lock.unlock();
System.out.println(Thread.currentThread().getName()+":\t 释放锁锁");
}
return "OK";
}
}
5、理解
一、时间设置
默认 lock() 小结
lock.lock ();
(1)默认指定锁时间为30s(看门狗时间)
(2)锁的自动续期:若是业务超长,运行期间自动给锁上新的 30s,不用担心业务时间过长,锁就自动过期
(3)加锁的业务只要运行完成,就不会给当前锁续期,及时不手动解锁,锁默认在30s 后自动删除。
指定时间 lock() 小结
问题:在锁到期的时候,不会自动续期。
(1)如果我们传递了锁的超时时间,就发送给 redis执行脚本,进行占锁,默认的超时时间既我们指的时间
(2)若是未指定锁的超时时间,就使用 30*1000【LockWatchdogTimeout看门狗的默认时间】
(3)只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔 10 s都会自动再次续到30s, internallockLeaseTime【看门狗时间/3s】
二、其他
1、互斥
在分布式高并发的条件下,我们最需要保证,同一时刻只能有一个线程获得锁,这是最基本的一点。
2、防止死锁
在分布式高并发的条件下,比如有个线程获得锁的同时,还没有来得及去释放锁,就因为系统故障或者其它原因使它无法执行释放锁的命令,导致其它线程都无法获得锁,造成死锁。所以分布式非常有必要设置锁的有效时间,确保系统出现故障后,在一定时间内能够主动去释放锁,避免造成死锁的情况。
6、读写锁
读写锁(Readers-Writer Lock)顾名思义是一把锁分为两部分:读锁和写锁,其中读锁允许多个线程同时获得,因为读操作本身是线程安全的,而写锁则是互斥锁,不允许多个线程同时获得写锁,并且写操作和读操作也是互斥的。总结来说,读写锁的特点是:读读不互斥、读写互斥、写写互斥。
实现:首先要配置redis,见前面的博客文章来源:https://www.toymoban.com/news/detail-654978.html
spring boot配置redis
读写锁代码文章来源地址https://www.toymoban.com/news/detail-654978.html
package com.example.springboot3test.controller;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/redission")
public class RedissionController {
@Resource
private RedissonClient redissonClient;
@Resource
private RedisTemplate redisTemplate;
private final static String LOCK="I_AM_LOCK";
// 并发写锁
@GetMapping("/write")
public String writeValue(){
RReadWriteLock myLock = redissonClient.getReadWriteLock ("my_lock");
RLock rLock = myLock.writeLock ( );
rLock.lock ();
String s = "";
try {
System.out.println ("写锁加锁成功..."+Thread.currentThread ().getId () );
s= UUID.randomUUID ().toString ();
Thread.sleep(20000);
redisTemplate.opsForValue ().set ("writeValue",s);
} catch (Exception e) {
e.printStackTrace ();
}
finally {
System.out.println ("写锁解锁成功..."+Thread.currentThread ().getId () );
rLock.unlock ();
}
return s;
}
// 并发读锁
@GetMapping("read")
public String readValue(){
RReadWriteLock myLock = redissonClient.getReadWriteLock ("my_lock");
RLock rLock = myLock.readLock ( );
rLock.lock ();
String s = "";
try {
System.out.println ("读锁加锁成功..."+Thread.currentThread ().getId ());
Thread.sleep(20000);
s = (String) redisTemplate.opsForValue ().get ("writeValue");
} catch (Exception e) {
e.printStackTrace ( );
}finally {
System.out.println ("读锁解锁成功..."+Thread.currentThread ().getId () );
rLock.unlock ();
}
return s;
}
}
到了这里,关于spring boot 实现Redisson分布式锁及其读写锁的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!