Redis分布式锁重要的原则就是,加锁、解锁要原子性。Redis官方网站提供了RedLock锁。但是我感觉那个锁比较臃肿,完全没有必要。如果集群中有故障。锁获取失败就可以了,Redis锁的机制就决定了他不能像数据库事物一样。所以集群中挡掉节点的情况,我不予考虑。
代码示例:
/**
* 获取redis锁,有重试机制
* @param lockKey 锁的key
* @param redisLockRequestId new 一个RedisLockRequestId 对象即可 --释放锁的时候用
* @param seconds 加锁时间 单位秒
* @return
*/
public boolean lock(String lockKey, RedisLockRequestId redisLockRequestId, int seconds) {
String requestId = UUID.randomUUID().toString()+"-"+System.currentTimeMillis();
redisLockRequestId.setRequestId(requestId);
long startNano = System.nanoTime();
//将秒转换成纳秒
Long secondsNanoTime = 1000L*1000000L*Integer.valueOf(seconds).longValue();
ThreadLocalRandom r = ThreadLocalRandom.current();
try{
//如果获取失败,重试n次锁时间内
while ((System.nanoTime() - startNano) < secondsNanoTime) {
String result = jedis.set(lockKey, redisLockRequestId.getRequestId(), new SetParams().nx().ex(seconds));
if (null!=result && "OK".equals(result)) {
return true;
}
// 短暂休眠,nano避免出现活锁
Thread.sleep(3, r.nextInt(500));
}
logger.info("lock error. key {} requestId {}", lockKey ,requestId);
return false;