315 lines
6.9 KiB
Markdown
315 lines
6.9 KiB
Markdown
---
|
||
sidebar_position: 3
|
||
title: 分布式锁
|
||
description: ZHub 分布式锁功能详解
|
||
---
|
||
|
||
# 分布式锁
|
||
|
||
ZHub 提供了分布式锁功能,支持多客户端环境下的资源互斥访问控制。
|
||
|
||
---
|
||
|
||
## 功能特性
|
||
|
||
- **分布式互斥**: 多个客户端实例之间互斥访问共享资源
|
||
- **自动超时**: 支持锁超时自动释放,避免死锁
|
||
- **非阻塞获取**: 支持尝试获取锁,立即返回结果
|
||
- **自动释放**: 支持手动释放锁,确保资源及时释放
|
||
|
||
---
|
||
|
||
## 基础使用
|
||
|
||
### 1. 阻塞式获取锁
|
||
|
||
```java
|
||
// 获取锁,会阻塞直到获取成功或超时
|
||
Lock lock = zhub.lock("resource-key", 30); // 30秒超时
|
||
try {
|
||
if (lock.success()) {
|
||
System.out.println("获取到锁,开始处理业务");
|
||
// 执行业务逻辑
|
||
Thread.sleep(5000); // 模拟业务处理
|
||
} else {
|
||
System.out.println("获取锁失败");
|
||
}
|
||
} finally {
|
||
lock.unLock(); // 释放锁
|
||
}
|
||
```
|
||
|
||
### 2. 非阻塞式获取锁
|
||
|
||
```java
|
||
// 尝试获取锁,立即返回结果
|
||
Lock lock = zhub.tryLock("resource-key", 30);
|
||
if (lock.success()) {
|
||
try {
|
||
System.out.println("获取到锁,开始处理业务");
|
||
// 执行业务逻辑
|
||
} finally {
|
||
lock.unLock(); // 释放锁
|
||
}
|
||
} else {
|
||
System.out.println("未获取到锁,资源被其他客户端占用");
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 高级用法
|
||
|
||
### 1. 锁超时处理
|
||
|
||
```java
|
||
public void processWithTimeout(String resourceKey, int timeoutSeconds) {
|
||
Lock lock = zhub.tryLock(resourceKey, timeoutSeconds);
|
||
if (!lock.success()) {
|
||
System.out.println("资源被占用,请稍后重试");
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// 业务处理
|
||
processResource(resourceKey);
|
||
} finally {
|
||
lock.unLock();
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 锁重试机制
|
||
|
||
```java
|
||
public boolean processWithRetry(String resourceKey, int maxRetries) {
|
||
for (int i = 0; i < maxRetries; i++) {
|
||
Lock lock = zhub.tryLock(resourceKey, 10);
|
||
if (lock.success()) {
|
||
try {
|
||
// 业务处理
|
||
processResource(resourceKey);
|
||
return true;
|
||
} finally {
|
||
lock.unLock();
|
||
}
|
||
}
|
||
|
||
// 等待一段时间后重试
|
||
try {
|
||
Thread.sleep(1000 * (i + 1)); // 递增等待时间
|
||
} catch (InterruptedException e) {
|
||
Thread.currentThread().interrupt();
|
||
break;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
```
|
||
|
||
### 3. 锁监控和统计
|
||
|
||
```java
|
||
public class LockMonitor {
|
||
private final ZHubClient zhub;
|
||
private final Map<String, LockInfo> lockStats = new ConcurrentHashMap<>();
|
||
|
||
public void acquireLock(String key, int timeout) {
|
||
long startTime = System.currentTimeMillis();
|
||
Lock lock = zhub.lock(key, timeout);
|
||
|
||
if (lock.success()) {
|
||
long acquireTime = System.currentTimeMillis() - startTime;
|
||
lockStats.put(key, new LockInfo(key, acquireTime, System.currentTimeMillis()));
|
||
System.out.println("锁获取成功,耗时: " + acquireTime + "ms");
|
||
}
|
||
}
|
||
|
||
public void releaseLock(String key) {
|
||
LockInfo info = lockStats.remove(key);
|
||
if (info != null) {
|
||
long holdTime = System.currentTimeMillis() - info.acquireTime;
|
||
System.out.println("锁持有时间: " + holdTime + "ms");
|
||
}
|
||
}
|
||
|
||
static class LockInfo {
|
||
String key;
|
||
long acquireTime;
|
||
long acquireDuration;
|
||
|
||
LockInfo(String key, long acquireDuration, long acquireTime) {
|
||
this.key = key;
|
||
this.acquireDuration = acquireDuration;
|
||
this.acquireTime = acquireTime;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 实现原理
|
||
|
||
### 服务端实现
|
||
|
||
ZHub 服务端锁管理结构:
|
||
|
||
```go
|
||
// 锁结构
|
||
type Lock struct {
|
||
Key string
|
||
UUID string
|
||
Duration int
|
||
Conn *ZConn
|
||
CreateTime time.Time
|
||
}
|
||
|
||
// 锁管理
|
||
type ZBus struct {
|
||
locks map[string][]*Lock // 锁映射表
|
||
// ... 其他字段
|
||
}
|
||
```
|
||
|
||
### 客户端实现
|
||
|
||
ZHub 客户端锁实现结构:
|
||
|
||
```java
|
||
public class Lock {
|
||
protected String name; // 锁名称
|
||
protected String uuid; // 锁唯一标识
|
||
protected int duration; // 锁持续时间
|
||
protected boolean success; // 获取是否成功
|
||
protected ZHubClient hubClient; // 客户端引用
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 最佳实践
|
||
|
||
### 1. 锁命名规范
|
||
|
||
```java
|
||
// 推荐:使用有意义的锁名称
|
||
String lockKey = "user:update:" + userId;
|
||
String lockKey = "order:process:" + orderId;
|
||
String lockKey = "cache:refresh:" + cacheType;
|
||
|
||
// 避免:使用无意义的锁名称
|
||
String lockKey = "lock1";
|
||
String lockKey = "temp";
|
||
```
|
||
|
||
### 2. 超时时间设置
|
||
|
||
```java
|
||
// 根据业务处理时间设置合理的超时时间
|
||
int shortTaskTimeout = 5; // 短任务:5秒
|
||
int mediumTaskTimeout = 30; // 中等任务:30秒
|
||
int longTaskTimeout = 300; // 长任务:5分钟
|
||
|
||
// 避免设置过短或过长的超时时间
|
||
int tooShort = 1; // 太短,可能导致获取失败
|
||
int tooLong = 3600; // 太长,可能导致资源长时间占用
|
||
```
|
||
|
||
### 3. 异常处理
|
||
|
||
```java
|
||
public void safeProcess(String resourceKey) {
|
||
Lock lock = null;
|
||
try {
|
||
lock = zhub.lock(resourceKey, 30);
|
||
if (lock.success()) {
|
||
// 业务处理
|
||
processResource(resourceKey);
|
||
}
|
||
} catch (Exception e) {
|
||
logger.error("处理资源时发生异常", e);
|
||
} finally {
|
||
if (lock != null && lock.success()) {
|
||
try {
|
||
lock.unLock();
|
||
} catch (Exception e) {
|
||
logger.error("释放锁时发生异常", e);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. 性能优化
|
||
|
||
```java
|
||
// 使用 tryLock 避免长时间阻塞
|
||
public boolean tryProcess(String resourceKey) {
|
||
Lock lock = zhub.tryLock(resourceKey, 5);
|
||
if (!lock.success()) {
|
||
return false; // 快速失败
|
||
}
|
||
|
||
try {
|
||
processResource(resourceKey);
|
||
return true;
|
||
} finally {
|
||
lock.unLock();
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
### 1. 死锁预防
|
||
|
||
- 避免嵌套锁的使用
|
||
- 设置合理的锁超时时间
|
||
- 确保锁的释放逻辑正确
|
||
|
||
### 2. 性能考虑
|
||
|
||
- 锁的粒度要适中,不要过细或过粗
|
||
- 避免长时间持有锁
|
||
- 考虑使用非阻塞的 tryLock
|
||
|
||
### 3. 错误处理
|
||
|
||
- 始终在 finally 块中释放锁
|
||
- 处理锁获取失败的情况
|
||
- 记录锁的使用情况用于监控
|
||
|
||
---
|
||
|
||
## 监控和调试
|
||
|
||
### 1. 锁状态查询
|
||
|
||
```bash
|
||
# 通过管理接口查看锁状态
|
||
curl http://127.0.0.1:711/_/info
|
||
```
|
||
|
||
### 2. 日志监控
|
||
|
||
```java
|
||
// 在客户端代码中添加锁使用日志
|
||
logger.info("尝试获取锁: " + resourceKey);
|
||
Lock lock = zhub.lock(resourceKey, 30);
|
||
if (lock.success()) {
|
||
logger.info("锁获取成功: " + resourceKey);
|
||
} else {
|
||
logger.warn("锁获取失败: " + resourceKey);
|
||
}
|
||
```
|
||
|
||
### 3. 性能指标
|
||
|
||
- 锁获取成功率
|
||
- 锁平均持有时间
|
||
- 锁等待时间
|
||
- 锁竞争频率
|