赞
踩
在分布式系统中,实现可靠的分布式锁是一项关键任务。Redis作为一个高性能的内存数据存储系统,提供了多种分布式锁方案。本文将介绍四种常见的Redis分布式锁方案,并给出每种方案的代码实现、原理解析以及优缺点分析。
该方案使用Redis的SETNX命令尝试设置一个不存在的锁键,并设置过期时间。如果SETNX返回1,表示锁获取成功,否则表示锁已被其他客户端持有。
// 获取锁
boolean lock = redis.setnx(key, value);
// 设置锁的过期时间
redis.expire(key, expireTime);
// 删除锁
redis.del(key);
// 存在问题
1.原子性问题,如果获取锁成功,但是设置锁的过期时间失败了,则锁就无法释放了.
2.有锁释放问题,线程1设置了锁,如果线程2拿到key,就可以直接释放锁.
3.锁时间问题,就算获取锁成功并且过期时间设置成功,如果处理业务时间超过锁时间,还是会被其他线程拿到锁.
该方案在方案一的基础上,为每个获取锁的客户端设置一个唯一的客户端ID(例如使用UUID)。客户端在释放锁时,需要验证持有锁的客户端ID是否匹配,避免误释放其他客户端持有的锁。
// 获取锁
boolean lock = redis.setnx(key, uuid);
// 设置锁的过期时间
redis.expire(key, expireTime);
// 删除锁
if(uuid.equals(redis.get(key))){
redis.del(key);
}
// 存在问题
这种方式还是有原子性问题、锁时间问题.
该方案基于RedLock算法,使用Redisson框架实现。RedLock算法通过在多个独立的Redis节点上获取锁,并通过大多数节点成功获取锁的原则来确保锁的可用性。Redisson提供了方便的API来实现RedLock算法,保证分布式锁的可靠性和高效性.
public String redLockTest() { String key = "redKey"; // 获取三个实例redis上的锁 RLock lock = redissonClient1.getLock(key); RLock lock2 = redissonClient2.getLock(key); RLock lock3 = redissonClient3.getLock(key); // 构建redLock RLock redLock = redissonClient.getRedLock(lock, lock2, lock3); // 加锁,超过半数redis实例加锁成功 -> 最终加锁成;否则失败 redLock.lock(); try { System.out.println("doSomething"); } finally { redLock.unlock(); } return "done"; } // 存在问题 1.牺牲了redis部分高性能,原来只要交互一次,现在需要交互多个redis节点. 2.极端情况下会造成不可用.例如如果你设置了3个节点,有2个节点宕机了,那么redlock就不可用了
redisson上红锁已经过期,所以不建议使用了。
该方案使用Redisson框架提供的分布式锁功能。Redisson是一个功能强大的Redis客户端,提供了分布式锁的高级功能和优化。它通过与Redis主从结构配合使用,并利用Redis的发布订阅机制和主从复制机制,确保分布式锁在整个主从结构中的可靠性和一致性.
// 获取锁
RLock lock = redisson.getLock(key);
lock.lock();
try {
System.out.println("doSomething");
} finally {
// 释放锁
lock.unlock();
}
推荐使用,详细底层逻辑请参考《Redisson底层分布式锁实现》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。