5. 看门狗机制
看门线程: 用于给当前key延长时间,保证也是线程的正常执行的过程中,锁不会过期
6. 分布式框架-Redisson
基于Redis+看门狗机制的分布式锁框架
6.1 Redission 介绍
Redisson在基于NIO的Netty框架上,充分的利⽤了Redis键值数据库提供的⼀系列优势,在Java实⽤⼯具包中常⽤接⼝的基础上,为使⽤者提供了⼀系列具有分布式特性的常⽤⼯具类。使得原本作为协调单机多线程并发程序的⼯具包获得了协调分布式多机多线程并发系统的能⼒,⼤⼤降低了设计和研发⼤规模分布式系统的难度。同时结合各富特⾊的分布式服务,更进⼀步简化了分布式环境中程序相互之间的协作
6.2 在SpringBoot应⽤中使⽤Redisson
-
添加依赖
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.12.0</version> </dependency>
-
配置yml
redisson: addr: singleAddr: host: redis://ajie.jimo.fun:6379 password: 12345 database: 0
-
配置RedissonClient
@Configuration public class RedissonConfig { @Value("${redisson.addr.singleAddr.host}") private String host; @Value("${redisson.addr.singleAddr.password}") private String password; @Value("${redisson.addr.singleAddr.database}") private int database; @Bean public RedissonClient redissonClient() { Config config = new Config(); config.useSingleServer().setAddress(host).setPassword(password).setDatabase(database); return Redisson.create(config); } }
-
在秒杀业务实现中注⼊RedissonClient对象
@Autowired private RedissonClient redissonClient;
6.3 Redisson⼯作原理
Redisson的工作原理图
6.4 Redisson使⽤扩展
6.4.1 Redisson单机连接
6.4.2 Redisson集群连接
-
application.yml
redisson: addr: cluster: hosts: redis://47.96.11.185:6370,...,redis://47.96.11.185:6373 password: 12345678
-
RedissonConfig——RedissonClient对象
@Configuration public class RedissonConfig { @Value("${redisson.addr.cluster.hosts}") private String hosts; @Value("${redisson.addr.cluster.password}") private String password; /** * 集群模式 * @return */ @Bean public RedissonClient redissonClient(){ Config config = new Config(); config.useClusterServers().addNodeAddress(hosts.split("[,]")) .setPassword(password) .setScanInterval(2000) .setMasterConnectionPoolSize(10000) .setSlaveConnectionPoolSize(10000); return Redisson.create(config); } }
6.4.3 Redisson主从连接
-
application.yml
redisson: addr: masterAndSlave: masterhost: redis://47.96.11.185:6370 slavehosts: redis://47.96.11.185:6371,redis://47.96.11.185:6372 password: 12345678 database: 0
-
RedissonConfig——RedissonClient对象
@Configuration public class RedissonConfig3 { @Value("${redisson.addr.masterAndSlave.masterhost}") private String masterhost; @Value("${redisson.addr.masterAndSlave.slavehosts}") private String slavehosts; @Value("${redisson.addr.masterAndSlave.password}") private String password; @Value("${redisson.addr.masterAndSlave.database}") private int database; /** * 主从模式 * @return */ @Bean public RedissonClient redissonClient(){ Config config = new Config(); config.useMasterSlaveServers() .setMasterAddress(masterhost) .addSlaveAddress(slavehosts.split("[,]")) .setPassword(password) .setDatabase(database) .setMasterConnectionPoolSize(10000) .setSlaveConnectionPoolSize(10000); return Redisson.create(config); } }
6.5 分布式锁总结
7.5.1 分布式锁特点
1、互斥性
和我们本地锁⼀样互斥性是最基本,但是分布式锁需要保证在不同节点的不同线程的互斥。
2、可重⼊性
同⼀个节点上的同⼀个线程如果获取了锁之后那么也可以再次获取这个锁。
3、锁超时
和本地锁⼀样⽀持锁超时,加锁成功之后设置超时时间,以防⽌线程故障导致不释放锁,防
⽌死锁。
4、⾼效,⾼可⽤
加锁和解锁需要⾼效,同时也需要保证⾼可⽤防⽌分布式锁失效,可以增加降级。redission是基于redis的,redis的故障就会导致redission锁的故障,因此redission⽀持单节点redis、reids主从、reids集群
5、⽀持阻塞和⾮阻塞
和 ReentrantLock ⼀样⽀持 lock 和 trylock 以及 tryLock(long timeOut)。
7.5.2 锁的分类
1、乐观锁与悲观锁
- 乐观锁
- 悲观锁
2、可重⼊锁和⾮可重⼊锁
- 可重⼊锁:当在⼀个线程中第⼀次成功获取锁之后,在此线程中就可以再次获取
- ⾮可重⼊锁
3、公平锁和⾮公平锁
- 公平锁:按照线程的先后顺序获取锁
- ⾮公平锁:多个线程随机获取锁
4、阻塞锁和⾮阻塞锁
- 阻塞锁:不断尝试获取锁,直到获取到锁为⽌
- ⾮阻塞锁:如果获取不到锁就放弃,但可以⽀持在⼀定时间段内的重试 ——在⼀段时间内如果没有获取到锁就放弃
7.5.3 Redission的使⽤
1、获取锁——公平锁和⾮公平锁
//获取公平锁
RLock lock = redissonClient.getFairLock(skuId);
//获取⾮公平锁
RLock lock = redissonClient.getLock(skuId);
2、加锁——阻塞锁和⾮阻塞锁
//阻塞锁(如果加锁成功之后,超时时间为30s;加锁成功开启看⻔狗,剩5s延⻓过期时间)
lock.lock();
//阻塞锁(如果加锁成功之后,设置⾃定义20s的超时时间)
lock.lock(20,TimeUnit.SECONDS);
//⾮阻塞锁(设置等待时间为3s;如果加锁成功默认超时间为30s)
boolean b = lock.tryLock(3,TimeUnit.SECONDS);
//⾮阻塞锁(设置等待时间为3s;如果加锁成功设置⾃定义超时间为20s)
boolean b = lock.tryLock(3,20,TimeUnit.SECONDS);
3、释放锁
lock.unlock();
4、应⽤示例
//公平⾮阻塞锁
RLock lock = redissonClient.getFairLock(skuId);
boolean b = lock.tryLock(3,20,TimeUnit.SECONDS);