1 Redisson 是什么?
Redisson 的宗旨是促进使用者对 Redis 的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。
如果你之前已经用 Redis 的话,那使用 Redisson 的话将会事半功倍,Redisson 提供了使用 Redis 的最简单和最便捷的方法。
1.1 redission的基础知识
● Netty 框架:Redisson 采用了基于 NIO 的Netty框架,不仅能作为 Redis 底层驱动客户端,具备提供对 Redis 各种组态形式的连接功能,对 Redis 命令能以同步发送、异步形式发送、异步流形式发送或管道形式发送的功能,LUA脚本执行处理,以及处理返回结果的功能
● 基础数据结构:将原生的 Redis Hash,List,Set,String,Geo,HyperLogLog等数据结构封装为 Java 里大家最熟悉的映射(Map),列表(List),集(Set),通用对象桶(Object Bucket),地理空间对象桶(Geospatial Bucket),基数估计算法(HyperLogLog)等结构;
● 分布式数据结构:这基础上还提供了分布式的多值映射(Multimap),本地缓存映射(LocalCachedMap),有序集(SortedSet),计分排序集(ScoredSortedSet),字典排序集(LexSortedSet),列队(Queue),阻塞队列(Blocking Queue),有界阻塞列队(Bounded Blocking Queue),双端队列(Deque),阻塞双端列队(Blocking Deque),阻塞公平列队(Blocking Fair Queue),延迟列队(Delayed Queue),布隆过滤器(Bloom Filter),原子整长形(AtomicLong),原子双精度浮点数(AtomicDouble),BitSet等 Redis 原本没有的分布式数据结构。
● 分布式锁:Redisson 还实现了 Redis文档中提到像分布式锁Lock这样的更高阶应用场景。事实上 Redisson 并没有不止步于此,在分布式锁的基础上还提供了联锁(MultiLock),读写锁(ReadWriteLock),公平锁(Fair Lock),红锁(RedLock),信号量(Semaphore),可过期性信号量(PermitExpirableSemaphore)和闭锁(CountDownLatch)这些实际当中对多线程高并发应用至关重要的基本部件。正是通过实现基于 Redis 的高阶应用方案,使 Redisson 成为构建分布式系统的重要工具。
这几个部分非常有必要参考官方的wiki!
redission 我们常用其来使用redis分布式锁,但其实它也提供了功能;使我们能更方便的使用redis!
2 整合reddison
2.1 引入依赖
你可以在中央仓库,查询redis依赖
mvnrepository.com/artifact/or…
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.20.1</version>
</dependency>
2.2 自定义配置
@Configuration
public class RedissonConfig {
@Bean(destroyMethod="shutdown")
public Redisson redisson() throws IOException {
Config config = new Config();
// 单机模式
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
// 集群模式
// config.useClusterServers().addNodeAddress("127.0.0.1:7004", "127.0.0.1:7001");
return Redisson.create(config);
}
}
Redisson实际上是 RedissonClient的实现!
我们也可以去看看 redisson-spring-boot-starter 中RedissonAutoConfiguration的配置方式!
如果你不熟悉Redisson,你可以认为其和redisTemplate是一样的;
3 使用案例
如果你对java多线程并发较为熟悉的话,这些api也是极容易理解的!
我们当做复习,研究并使用下这些api;
3.1 可重入锁
redisson提供的可重入锁是本次研究的重点;
我们会深入源码去解析之;
1.常用API
注意waitTime和leaseTime的区别
waitTime 等待加锁的时间
leaseTime 锁持续时长,若没设置,则redission会将其设置为-1,将采用续命锁逻辑
2.使用方式
@Autowire
private Redisson redisson;
public void workWithLock() {
// 针对业务主键加锁
RLock lock = redisson.getLock("product:1001:lock");
lock.lock();
// 同ReentrantLock,未获取到锁,则会放弃执行机会
// lock.tryLock(15, TimeUnit.SECONDS);
//
try {
doWork();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
@Autowire
private Redisson redisson;
public void workWithTryLock() {
// 针对业务主键加锁
RLock lock = redisson.getLock("product:1001:lock");
try {
// 同ReentrantLock,未获取到锁,则会放弃执行机会
if (!lock.tryLock(15, TimeUnit.SECONDS)) {
// 若未获得锁,则可以投递至延迟队列,重新等待执行机会
return;
}
doWork();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
redisson实现的分布式锁,也是和jdk实现的锁是高度一致的;
只要当你理解jdk中高并发工具的使用,才能更好地理解并掌握使用分布式锁!
3.2 分布式读写锁
1 使用方式
public void update() {
RReadWriteLock readWriteLock = redisson.getReadWriteLock("product:1001:rwlock");
RLock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
// 更新时使用写锁
doUpdateWork();
} finally {
writeLock.unlock();
}
}
public Product get() throws InterruptedException {
RReadWriteLock readWriteLock = redisson.getReadWriteLock("product:1001:rwlock");
RLock rLock = readWriteLock.readLock();
rLock.lock();
try {
// 在读场景下,使用读锁
doGetWork();
} finally {
rLock.unlock();
}
return product;
}
读写锁,适合读多写锁的业务场景!
请不要在频繁更新场景下,使用读写锁!
时间限制,我们暂时先跳过源码解析!
todo-task
3.3 信号量
3.4 红锁(redLock)
3.5 RedissonLocalCachedMap