本片文章为 分布式锁 相关的系列文章
本系列文章 将从 缓存的使用 本地锁 ** 一直写到 **分布式锁 以及相关的一些 知识点 问题
上一篇总结出Redis+LUA脚本只在单机版中 分布式锁有效 集群环境中可能出现问题 引出Redisson-redlock
上篇文章说到Redis+Lua脚本 做分布式锁的局限性 (在集群情况下失效)
解决方案
more >>Redisson
- Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务
- Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。
- github项目链接,https://github.com/redisson/redisson,~~我就不照本宣科了~~
内存数据网格 (百度百科):
- 内存网格(RAM(Random Access Memory)Grid)是一种面向广域网上内存资源共享的新型网格系统。它的主要目标是在物理内存不足的情况下,提高内存密集型应用或IO密集型应用的系统性能。内存网格的应用效果取决于网络通信开销。在减少或隐藏网络通信开销的情况下,其性能可以进一步提高。
分布式锁和同步器
- 可重入锁(Reentrant Lock)
基于Redis的Redisson分布式可重入锁
RLock
Java对象实现了java.util.concurrent.locks.Lock
接口。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1
2
3
4
5 // Renntrant Lock 也称为 RLock
RLock lock = redisson.getLock("anyLock");
// 最常见的使用方法
lock.lock();
lock.unlock(); 使用Reentrant Lock这种分布式锁的 Redisson 节点 宕机后 如果这个锁正好处在于 锁定 的状态 那么这个锁 就会变成 死锁
还有个问题 如果 给锁 增加了 过期时间 但是 过期时间 小于 业务执行时间 也就是说 业务还没有执行完毕 但是 设定的过期时间到了 此情况下 也会导致 锁资源被释放 并且在后面进入的线程 还会出现 误删除 其他锁的情况
Redisson 内部 提供了一个 监控锁的 看门狗 它的作用 是在 redisson 实例被关闭前 不断的延长锁的有效期 默认情况下 看门狗的检查锁的超时时间为30秒 也可以通过修改Config.lockWatchdogTimeout来另行制定
此外 Redisson 还通过 加锁的方式 提供了 leaseTime 的参数 来指定 加锁时间 超过这个时间后 锁 便自动解开
1
2
3
4
5
6
7
8
9
10
11
12
13 // 加锁以后10秒钟自动解锁
// 无需调用unlock方法手动解锁
lock.lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
try {
...
} finally {
lock.unlock();
}
}Redisson同时还为分布式锁提供了异步执行的相关方法
1
2
3
4 RLock lock = redisson.getLock("anyLock");
lock.lockAsync();
lock.lockAsync(10, TimeUnit.SECONDS);
Future<Boolean> res = lock.tryLockAsync(100, 10, TimeUnit.SECONDS);RLock 对象 完全符合 Java的Lock规范 也就是说 只有拥有锁的 进程 才能解锁 其他进程解锁 会 抛出异常(IllegalMonitorStateException)如果遇到其他进程也能解锁的情况 请使用 分布式信号量Semaphore 对象