分布式锁框架-Redisson
- 一、Redisson介绍
- 二、在SpringBoot中使用Redisson
- 三、Redisson工作原理
- 四、Redisson使用扩展
- 4.1、Redisson单机连接
- 4.2、Redisson集群连接
- 4.3、Redisson主从连接
- 五、分布式锁总结
- 5.1、分布式锁特点
- 5.2、锁的分类
- 5.3、Redission的使用
基于Redis+看门狗机制的分布式锁框架
一、Redisson介绍
官网链接:https://redisson.org/
Redisson是架设在Redis基础上的一个Java驻内存数据网格(In-Memory Data Grid)。
Redisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在Java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。
主要有以下几大特性:
云Redis管理、多样Redis配置支持、丰富连接方式、分布式对象、分布式集合、分布式锁、分布式服务、多种序列化方式、三方框架整合、完善工具等
- 支持云托管服务模式(同时支持亚马逊云的ElastiCache Redis和微软云的Azure Redis Cache):
- 自动发现主节点变化
- 支持Redis集群模式(同时支持亚马逊云的ElastiCache Redis Cluster和微软云的Azure Redis Cache):
- 自动发现主从节点
- 自动更新状态和组态拓扑
- 自动发现槽的变化
- 支持Redis哨兵模式:
- 自动发现主、从和哨兵节点
- 自动更新状态和组态拓扑
- 支持Redis主从模式
- 支持Redis单节模式
- 多节点模式均支持读写分离:从读主写,主读主写,主从混读主写
- 所有对象和接口均支持异步操作
- 自行管理的弹性异步连接池
- 所有操作线程安全
- 支持LUA脚本
- 提供分布式对象
通用对象桶(Object Bucket)、二进制流(Binary Stream)、地理空间对象桶(Geospatial Bucket)、BitSet、原子整长形(AtomicLong)、原子双精度浮点数(AtomicDouble)、话题(订阅分发)、布隆过滤器(Bloom Filter)和基数估计算法(HyperLogLog) - 提供分布式集合
映射(Map)、多值映射(Multimap)、集(Set)、列表(List)、有序集(SortedSet)、计分排序集(ScoredSortedSet)、字典排序集(LexSortedSet)、列队(Queue)、双端队列(Deque)、阻塞队列(Blocking Queue)、有界阻塞列队(Bounded Blocking Queue)、阻塞双端列队(Blocking Deque)、阻塞公平列队(Blocking Fair Queue)、延迟列队(Delayed Queue)、优先队列(Priority Queue)和优先双端队列(Priority Deque) - 提供分布式锁和同步器
可重入锁(Reentrant Lock)、公平锁(Fair Lock)、联锁(MultiLock)、红锁(RedLock)、读写锁(ReadWriteLock)、信号量(Semaphore)、可过期性信号量(PermitExpirableSemaphore)和闭锁(CountDownLatch) - 提供分布式服务
分布式远程服务(Remote Service, RPC)、分布式实时对象(Live Object)服务、分布式执行服务(Executor Service)、分布式调度任务服务(Scheduler Service)和分布式映射归纳服务(MapReduce)
13.支持Spring框架 - 提供Spring Cache集成
- 提供Hibernate Cache集成
- 提供JCache实现
- 提供Tomcat Session Manager
- 提供Spring Session集成
- 支持异步流方式执行操作
- 支持Redis管道操作(批量执行)
- 支持安卓(Andriod)系统
- 支持断线自动重连
- 支持命令发送失败自动重试
- 支持OSGi
- 支持采用多种方式自动序列化和反序列化(Jackson JSON,Avro,Smile,CBOR,MsgPack,Kryo,FST,LZ4,Snappy和JDK序列化)
- 超过1000个单元测试
二、在SpringBoot中使用Redisson
- 添加依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.21.3</version>
</dependency>
- 配置yml
redisson:
addr:
singleAddr:
host: redis://127.0.0.1:6379
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).setDatabase(database);
return Redisson.create(config);
}
}
三、Redisson工作原理
四、Redisson使用扩展
4.1、Redisson单机连接
- 配置yml
redisson:
addr:
singleAddr:
host: redis://127.0.0.1:6379
password: 12345678
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);
}
}
4.2、Redisson集群连接
- 配置yml
redisson:
addr:
cluster:
hosts: redis://127.0.0.1:6379,...,redis://127.0.0.1:6388
password: 12345678
- 配置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);
}
}
4.3、Redisson主从连接
- 配置yml
redisson:
addr:
masterAndSlave:
masterhost: redis://127.0.0.1:6380
slavehosts: redis://127.0.0.1:6381,redis://127.0.0.1:6382
password: 12345678
database: 0
- 配置RedissonClient
@Configuration
public class RedissonConfig {
@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);
}
}
五、分布式锁总结
5.1、分布式锁特点
- 互斥性
和我们本地锁⼀样互斥性是最基本,但是分布式锁需要保证在不同节点的不同线程的互斥。 - 可重入性
同⼀个节点上的同⼀个线程如果获取了锁之后那么也可以再次获取这个锁。 - 锁超时
和本地锁⼀样支持锁超时,加锁成功之后设置超时时间,以防止线程故障导致不释放锁,防止死锁。 - 高效,高可用
加锁和解锁需要高效,同时也需要保证高可用防止分布式锁失效,可以增加降级。redission是基于redis的,redis的故障就会导致redission锁的故障,因此redission支持单节点redis、reids主从、reids集群 - 支持阻塞和非阻塞
和 ReentrantLock ⼀样支持 lock 和 trylock 以及 tryLock(long timeOut)。
5.2、锁的分类
- 乐观锁与悲观锁
- 乐观锁
- 悲观锁
- 可重入锁和非可重入锁
- 可重入锁:当在⼀个线程中第⼀次成功获取锁之后,在此线程中就可以再次获取
- 非可重入锁
- 公平锁和非公平锁
- 公平锁:按照线程的先后顺序获取锁
- 非公平锁:多个线程随机获取锁
- 阻塞锁和非阻塞锁
- 阻塞锁:不断尝试获取锁,直到获取到锁为止
- 非阻塞锁:如果获取不到锁就放弃,但可以支持在⼀定时间段内的重试——在⼀段时间内如果没有获取到锁就放弃
5.3、Redission的使用
- 获取锁——公平锁和非公平锁
//获取公平锁
RLock lock = redissonClient.getFairLock("xxid");
//获取⾮公平锁
RLock lock = redissonClient.getLock("xxid");
- 加锁——阻塞锁和非阻塞锁
//阻塞锁(如果加锁成功之后,超时时间为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);
- 释放锁
lock.unlock();
- 应用示例
//公平⾮阻塞锁
RLock lock = redissonClient.getFairLock("xxid");
boolean b = lock.tryLock(3, 20, TimeUnit.SECONDS);