分布式锁实现 java
时间: 2024-12-30 12:26:45 浏览: 9
### Java 中实现分布式锁的最佳实践
#### 使用 ZooKeeper 实现分布式锁
ZooKeeper 是一种高效的协调服务,能够提供强一致性保障。其临时顺序节点特性非常适合用于构建分布式锁机制。
```java
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
public class ZKLock {
private final String lockPathPrefix = "/lock_";
public void acquireLock(ZooKeeper zk, String path) throws Exception {
// 创建临时顺序节点
String createdNode = zk.create(lockPathPrefix, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
List<String> childrenNodes = zk.getChildren(path, false);
Collections.sort(childrenNodes);
if (createdNode.equals(path + "/" + childrenNodes.get(0))) {
System.out.println("成功获取到锁");
} else {
Watcher watcher = event -> {
try {
if(event.getType() == Event.EventType.NodeDeleted){
acquireLock(zk, path);
}
} catch(Exception e) {
throw new RuntimeException(e.getMessage());
}
};
Stat stat = zk.exists(createdNode.substring(0, createdNode.lastIndexOf("_")), watcher);
while(stat != null){
Thread.sleep(100L);
stat = zk.exists(createdNode.substring(0, createdNode.lastIndexOf("_")), watcher);
}
}
}
public void releaseLock(ZooKeeper zk, String lockPath) throws Exception {
zk.delete(lockPath, -1);
System.out.println("释放锁:" + lockPath);
}
}
```
此代码展示了基于 ZooKeeper 的分布式锁基本框架[^1]。
#### 使用 Redis 实现分布式锁
Redis 提供了原子命令 `SET` 和 `DEL` 来支持简单的分布式锁功能。为了提高可靠性,建议采用 Redlock 算法来增强安全性。
```java
import redis.clients.jedis.Jedis;
public class RedisDistributedLock {
private static final long DEFAULT_EXPIRE_TIME_MS = 30 * 1000; // 默认过期时间设为30秒
/**
* 尝试加锁
*/
public boolean tryAcquire(String key, String value, int expireTimeMs) {
Jedis jedis = null;
try {
jedis = getJedis();
String result = jedis.set(key, value, "NX", "PX", expireTimeMs);
return "OK".equals(result);
} finally {
close(jedis);
}
}
/**
* 解锁
*/
public void unlock(String key, String value) {
Jedis jedis = null;
try {
jedis = getJedis();
String luaScript =
"if redis.call('get', KEYS[1]) == ARGV[1] then "
+"return redis.call('del', KEYS[1]) "
+"else return 0 end";
Object evalResult = jedis.eval(luaScript, Arrays.asList(key), Arrays.asList(value));
if ("0".equals(evalResult.toString())) {
throw new IllegalMonitorStateException("您试图解锁不属于您的锁!");
}
} finally {
close(jedis);
}
}
}
```
上述代码实现了利用 Lua 脚本安全地解除 Redis 锁的方法[^2]。
阅读全文