其他的redis分布式锁的演变过程以及存在的缺陷(比如不是原子性,错误解锁,主从复制导致主节点锁信息没有及时同步到从节点等等)不在本文讨论;
1-Redlock介绍
官方文档:
https://redis.io/docs/manual/patterns/distributed-locks/
![](https://i-blog.csdnimg.cn/blog_migrate/4a3b88312f4e67176087d8bfc2ca01b1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/cd90bf67d1d40ce9ebcb056e02d67619.png)
大概思想就是:准备N(N>=3的奇数,建议是5个)个redis master实例;如果获取锁得到大于等于(N/2+1)个实例通过,那么就成功获取到锁...
该方案也是基于(set 加锁、Lua 脚本解锁)进行改良的,所以redis之父antirez 只描述了差异的地方,大致方案如下。假设我们有N个Redis主节点,例如 N = 5这些节点是完全独立的,我们不使用复制或任何其他隐式协调系统,
为了取到锁客户端执行以下操作:
1 | 获取当前时间,以毫秒为单位; |
2 | 依次尝试从5个实例,使用相同的 key 和随机值(例如 UUD)获取锁。当向Redis 请求获取锁时,客户端应该设置一个超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为 10 秒,则超时时间应该在 5-50 毫秒之间。这样可以防止客户端在试图与一个宕机的 Redis 节点对话时长时间处于阻寒状态。如果一个实例不可用,客户端应该尽快尝试去另外一个 Redis 实例请求获取锁; |
3 | 客户端通过当前时间减去步骤 1 记录的时间来计算获取锁使用的时间。当且仅当从大多数(N/2+1,这里是 3 个节点)的Redis 节点都取到锁,并且获取锁使用的时间小于锁失效时间时,锁才算获取成功; |
4 | 如果取到了锁,其真正有效时间等于初始有效时间减去获取锁所使用的时间(步骤 3 计算的结果)。 |
5 | 如果由于某些原因未能获得锁(无法在至少 N/2 + 1个 Redis 实例获取锁、或获取锁的时间超过了有效时间),客户端应该在所有的 Redis 实例上进行解锁(即便某些Redis实例根本就没有加锁成功,防止某些节点获取到锁但是客户端没有得到响应而导致接下来的一段时间不能被重新获取锁)。 |
2-分布式锁应该具备的特点和条件
互斥
高性能的获取和释放锁
具备可重入性
锁失效机制,自动解锁,防止死锁
具备非阻塞性
3-Java客户端实现
官方文档:
https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95
3.1-使用方式
单节点设置,还有很多其他参数:
详细查看上述文档链接的2.6章节信息:
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
SingleServerConfig singleServerConfig = config.useSingleServer();
singleServerConfig.setAddress("redis://192.168.10.130:6379");
singleServerConfig.setDatabase(0);
//密码无不设置
// singleServerConfig.setPassword(null);
return Redisson.create(config);
}
RLock rLock = redissonClient.getLock("REDIS_LOCK_KEY");
try {
//加锁
rLock.lock();
//处理业务逻辑
} catch (Exception e) {
//记录日志
}finally {
rLock.unlock();
}
如果负责储存某些分布式锁的某些Redis节点宕机以后,而且这些锁正好处于锁住的状态时,这些锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
3.2-其他高级功能
分布式对象(地理空间对象桶,BitSet, 布隆过滤器,基数估计算法HyperLogLog),分布式集合以及基于分布式的 可重入锁,公平锁,读写锁,信号量,闭锁等....
![](https://i-blog.csdnimg.cn/blog_migrate/177c8c61859f61f1ddfc27ef800943da.png)