在集群环境中实现分布式锁有很多方法,最常见的是使用数据库(大部分数据库都有內建的锁或原子操作)或zookeeper管理共享资源。如果不想搭建zookeeper集群或者未来有计划更换数据库,使用Redis是一个不错的方案。
Redis支持setnx锁定key。而Redisson是一个非常不错的java开源Redis客户端,它实现了Redis锁。
我们首先定义一个分布式锁接口(面向接口编程,对不同的分布式锁实现提供不同的实现类)。
public interface DistributedLocker {
public <T> T lock(String resourceName,
AquiredLockWorker<T> worker) throws UnableToAquireLockException, Exception;
public <T> T lock(String resourceName,
AquiredLockWorker<T> worker, int lockTime) throws
UnableToAquireLockException, Exception;
}
public interface AquiredLockWorker<T> {
public T invokeAfterLockAquire() throws Exception;
}
以下是基于Resisson和Redis的分布式锁实现
@Component
public class RedisLocker implements DistributedLocker{
private final static String LOCKER_PREFIX = "lock:";
@Autowired
private RedissonConnector rdsConnector;
@Override
public <T> T lock(String resourceName, AquiredLockWorker<T> worker)
throws InterruptedException, UnableToAquireLockException, Exception {
return lock(resourceName, worker, 100);
}
@Override
public <T> T lock(String resourceName, AquiredLockWorker<T> worker,
int lockTime) throws UnableToAquireLockException,
Exception {
RedissonClient redisson = rdsConnector.getClient();
RLock lock = redisson.getLock(LOCKER_PREFIX + resourceName);
// Wait for 100 seconds seconds and automatically unlock it after lockTime seconds
boolean success = lock.tryLock(100, lockTime, TimeUnit.SECONDS);;
if (success) {
try {
return worker.invokeAfterLockAquire();
} finally {
lock.unlock();
}
}
throw new UnableToAquireLockException();
}
}