应定义语义明确的自定义异常类(如DistributedLockAcquireFailureException)并在锁获取失败时主动throw,而非依赖框架抛出;需显式判断tryLock等返回值,区分业务失败与系统异常,配合全局异常处理器返回HTTP 423。

在分布式锁获取失败时抛出 Java 自定义异常,核心是:**定义清晰的业务异常类 + 在加锁逻辑中主动判断并 throw**,而不是依赖底层框架自动抛出。
定义明确语义的自定义异常
避免直接 throw RuntimeException 或泛化的 Exception,应创建有业务含义的异常类,例如:
public class DistributedLockAcquireFailureException extends RuntimeException {
private final String lockKey;
public DistributedLockAcquireFailureException(String lockKey) {
super("Failed to acquire distributed lock for key: " + lockKey);
this.lockKey = lockKey;
}
public DistributedLockAcquireFailureException(String lockKey, String message) {
super(message + " (key: " + lockKey + ")");
this.lockKey = lockKey;
}
public String getLockKey() {
return lockKey;
}
}
这样便于上层统一捕获、日志记录、监控告警或重试策略识别。
在锁获取逻辑中显式判断并抛出
无论使用 Redis(如 Redisson)、ZooKeeper 还是 Etcd,锁的“获取失败”通常表现为返回 false 或超时,**这不是异常,而是正常流程分支**。你需要主动检查结果并 throw:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用 Redisson 举例(基于 tryLock):
RLock lock = redissonClient.getLock("order:123");
boolean isLocked = lock.tryLock(3, 10, TimeUnit.SECONDS); // 等待3秒,持有10秒
if (!isLocked) {
throw new DistributedLockAcquireFailureException("order:123", "Distributed lock acquisition timed out");
}
// ✅ 后续业务逻辑
- 若封装了工具类(推荐),应在工具方法内完成判断和抛出:
public static void requireLock(RedissonClient client, String key, long waitTime, long leaseTime) {
RLock lock = client.getLock(key);
if (!lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS)) {
throw new DistributedLockAcquireFailureException(key);
}
}
配合全局异常处理统一响应(可选但实用)
在 Spring Boot 项目中,可添加 @ControllerAdvice 捕获该异常,返回标准错误格式:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(DistributedLockAcquireFailureException.class)
public ResponseEntity<ApiResponse> handleLockFailure(
DistributedLockAcquireFailureException e) {
log.warn("Lock acquire failed for key: {}", e.getLockKey());
return ResponseEntity.status(423).body(
ApiResponse.fail("BUSINESS_LOCK_UNAVAILABLE", e.getMessage())
);
}
}
HTTP 423 Locked 是语义最贴合的状态码,比 500 或 409 更准确。
注意与底层异常区分
不要把网络超时(如 JedisConnectionException)、序列化失败等底层异常混同为“获取失败”:
- 分布式锁获取失败 = 业务语义上的“锁已被占用且等待超时”,属于预期内的控制流
- 连接异常、序列化异常 = 系统级故障,应单独捕获并记录 error 日志,可能触发熔断或告警
确保自定义异常只在明确知道锁不可得时抛出,而非在 catch 块里“兜底 throw”。

















