主题
Redis 分布式锁使用指南
@DLock 注解(推荐)
基于 DistributedLockAspectConfiguration 切面实现,自动处理锁的获取、释放和异常。
基础示例
java
@Service
public class OrderService {
/**
* 创建订单
* 锁 Key: order:create:{orderId}
*/
@DLock(value = "#orderId", prefix = "order:create", waitTime = 50, leaseTime = 90)
public void createOrder(String orderId, OrderDTO orderDTO) {
doCreateOrder(orderId, orderDTO);
}
/**
* 扣减库存 - 使用 SpEL 表达式
* 锁 Key: stock:deduct:{skuId}
*/
@DLock(value = "#skuId", prefix = "stock:deduct")
public void deductStock(Long skuId, Integer quantity) {
doDeductStock(skuId, quantity);
}
/**
* 更新用户信息 - 使用对象属性
* 锁 Key: user:update:{user.id}
*/
@DLock(value = "#user.id", prefix = "user:update")
public void updateUser(User user) {
doUpdateUser(user);
}
}参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
value | 锁的 Key 值,支持 SpEL 表达式 | - |
prefix | 锁 Key 的前缀,最终格式为 prefix:value | - |
waitTime | 获取锁的最大等待时间(秒) | 50 |
leaseTime | 锁的持有时间(秒),超过后自动释放 | 90 |
异常处理
获取锁超时时抛出 RuntimeException,提示"请稍后重新重试"。
编程式锁
仅在注解无法满足的动态场景下使用(如锁 Key 运行时动态决定)。
基础示例
java
@Service
public class OrderService {
@Autowired
private RedisTemplatePrivateWrapper redisWrapper;
public void createOrder(String orderId) {
// 获取锁(重试 3 秒,锁有效期 10 秒)
String lockValue = redisWrapper.preemptionKeyLockRetryByAuto(orderId, 10000, 3000);
if (lockValue != null) {
try {
doCreateOrder(orderId);
} finally {
redisWrapper.releaseSecretKeyLock(orderId, lockValue);
}
}
}
}常用方法
| 方法 | 说明 |
|---|---|
preemptionKeyLockRetryByAuto(lockID, lockMillisecond, retryMillisecond) | 自动选择加锁策略,返回锁值 |
preemptionKeyLockRetryByNewSet(lockID, lockMillisecond, retryMillisecond) | 使用 SET NX EX 策略(Redis 2.6.12+) |
preemptionKeyLockRetryBySetNX(lockID, lockMillisecond, retryMillisecond) | 使用 SETNX + EXPIRE 策略(兼容旧版本) |
releaseSecretKeyLock(lockID, lockValue) | 安全释放锁(验证锁值防止误删) |
delayKeyLock(lockID, lockValue, delayMillisecond) | 延长锁持有时间 |
获取锁详情信息
java
EnumMap<LockInfoCodeEnum, Object> lockInfo = redisWrapper.preemptionKeyLockRetryByAutoM(
"order:123", 10000, 3000);
String lockValue = (String) lockInfo.get(LockInfoCodeEnum.LOCK_VALUE);
Long sendTime = (Long) lockInfo.get(LockInfoCodeEnum.LOCK_SEND_TIME);
Long backTime = (Long) lockInfo.get(LockInfoCodeEnum.LOCK_BACK_TIME);使用建议
| 场景 | 推荐方式 |
|---|---|
| 固定 Key 的同步控制 | @DLock 注解 |
| 动态 Key 的同步控制 | 编程式锁 |
| 简单业务方法加锁 | @DLock 注解 |
| 复杂锁逻辑控制 | 编程式锁 |
