一 redision简介
1.1 redission介绍
Redisson分布式锁是一种基于redis实现的分布式锁,它利用redis的setnx命令实现分布式锁的互斥访问。同时还支持锁的自动续期功能,可以避免因为某个进程崩溃或者网络故障导致锁无法释放的情况。
只要线程一加锁成功,就会启动一个watchdog看门狗,它是一个后台线程,会每隔10秒检查一下,默认生存时间只有30秒,如果线程A还持有锁,那么就会不断的延长锁key的生存时间。可以使用reentracklock,公平锁,读写锁,信号量,闭锁等锁进行加锁操作,完成后然后释放锁。其他线程BCD判断加锁的次数为0,就可以进行加锁操作。
因此,Redisson就是使用watch dog解决了「锁过期释放,业务没执行完」的问题。
如果使用这个分布式锁的Redisson节点实例客户端宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout
来另行指定。
1.2 常用锁介绍
1.2.1 重入锁
基于Redis的Redisson分布式可重入锁RLock
Java对象实现了java.util.concurrent.locks.Lock
接口。 Redisson还通过加锁的方法提供了leaseTime
的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
1.2.2 公平锁
它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。所有请求线程会在一个队列中排队,当某个线程出现宕机时,Redisson会等待5秒后继续下一个线程,也就是说如果前面有5个线程都处于等待状态,那么后面的线程会等待至少25秒。
1.2.3 联锁
基于Redis的Redisson分布式联锁RedissonMultiLock对象可以将多个RLock
对象关联为一个联锁,每个RLock
对象实例可以来自于不同的Redisson实例。要求每一个节点都得满足。则获取锁成功
1.2.4 redlock 红锁
基于Redis的Redisson红锁RedissonRedLock
对象实现了Redlock介绍的加锁算法。该对象也可以用来将多个RLock
对象关联为一个红锁,每个RLock
对象实例可以来自于不同的Redisson实例。大部分节点满足则获取锁成功
1.2.5 信号量
基于Redis的Redisson的分布式信号量(Semaphore)Java对象RSemaphore
采用了与java.util.concurrent.Semaphore
相似的接口和用法。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1.2.6 读写锁
分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。
1.2.7 闭锁
1.3 案例操作
1.3.1 pom依赖配置
1.3.2 redisson配置文件
package com.atguigu.distributed.lock.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName: RedissonConfig
* @Description: TODO
* @Author: admin
* @Date: 2024/01/14 23:18:50
* @Version: V1.0
**/
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient(){
Config config = new Config();
// 可以用"rediss://"来启用SSL连接
// config.useSingleServer().setAddress("redis://192.168.43.4:6379");
config.useSingleServer().setAddress("redis://192.168.43.4:6379").setPassword("123456");
return Redisson.create(config);
}
}
1.3.3 核心加锁代码
@Autowired
private RedissonClient redissonClient;
public void checkAndLockByRedisson() {
// 加锁,获取锁失败重试
RLock lock = this.redissonClient.getLock("rlock");
lock.lock();
System.out.println("redisson的锁....");
// 先查询库存是否充足
Stock stock = this.stockMapper.selectById(1L);
// 再减库存
if (stock != null && stock.getCount() > 0){
stock.setCount(stock.getCount() - 1);
this.stockMapper.updateById(stock);
}
// 释放锁
lock.unlock();
}
1.3.4 controller调用
1.3.5 验证调试
1.启动服务
2.启动redis
[root@localhost export]# redis-server /myredis/redis.conf
[root@localhost export]# redis-cli -a 123456 -p 6379
3.启动zk
[root@localhost export]# cd apache-zookeeper-3.7.0-bin/
[root@localhost apache-zookeeper-3.7.0-bin]# cd bin
[root@localhost bin]# ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /root/export/apache-zookeeper-3.7.0-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
4.启动nginx
5.启动jemter
6.查看结果
2.查看结果
7.查看db结果
测试前
测试后