Skip to content

🔒 分布式锁

📖 功能介绍

TIP

基于Redis实现的分布式锁服务,支持注解和工具类两种使用方式,可以有效解决分布式系统中的并发控制问题。

Syntax error in textmermaid version 11.5.0

⚙️ 全局配置

基础配置参数

参数名说明默认值示例
max-expire锁最大过期时间30s60s
acquire-timeout获取锁超时时间30s10s
yaml
wueasy:  
  lock: 
    max-expire: 30s      # 最大过期时间,0表示永不过期
    acquire-timeout: 30s # 获取锁超时时间,0表示一直等待

📝 使用方式

1. 注解方式 (@Lock)

注解参数说明

参数名说明默认值示例
group锁分组方法名称"userLock"
keys锁的key(支持SpEL)-"#p0.accountNo"
maxExpire最大过期时间全局配置30000
acquireTimeout获取锁超时时间全局配置5000
msg获取锁失败提示"请求超时,请重试""操作频繁"

使用示例

java
@RestController
@RequestMapping("/user")
public class UserController {
    
    @PostMapping("/login")
    @Lock(
        group = "userLogin",
        keys = "#p0.accountNo",
        maxExpire = 30000,
        acquireTimeout = 5000,
        msg = "登录请求频繁,请稍后再试"
    )
    public Mono<ResultVo<SessionVo>> login(@RequestBody @Valid LoginDto dto) {
        return Mono.just(ResultVo.ok(loginService.login(dto)));
    }
}

2. 工具类方式 (RedisDistributedLock)

核心方法

java
public class RedisDistributedLock {
    /**
     * 获取锁
     * @param lockKey 锁标识
     * @param maxExpire 过期时间
     * @param acquireTimeout 获取超时时间
     * @return 是否获取成功
     */
    boolean lock(String lockKey, Duration maxExpire, Duration acquireTimeout);
    
    /**
     * 释放锁
     * @param lockKey 锁标识
     * @return 是否释放成功
     */
    boolean unlock(String lockKey);
}

使用示例

java
@Service
public class UserService {
    @Autowired
    private RedisDistributedLock lock;
    
    public void updateUser(UserDto dto) {
        String lockKey = "user:" + dto.getId();
        boolean acquired = false;
        
        try {
            // 获取锁,30秒过期,5秒超时
            acquired = lock.lock(lockKey, 
                Duration.ofSeconds(30), 
                Duration.ofSeconds(5));
                
            if (!acquired) {
                throw new RuntimeException("操作频繁,请稍后再试");
            }
            
            // 执行业务逻辑
            doUpdate(dto);
            
        } finally {
            // 释放锁
            if (acquired) {
                lock.unlock(lockKey);
            }
        }
    }
}

💡 最佳实践

1. 锁粒度控制

  • 避免锁粒度过大影响性能
  • 确保锁的唯一性
  • 合理设置过期时间

2. 异常处理

  • 必须在finally中释放锁
  • 捕获并处理获取锁异常
  • 添加获取锁失败重试机制

3. 性能优化

  • 合理设置超时时间
  • 避免长时间持有锁
  • 考虑使用锁的替代方案

⚠️ 注意事项

  1. 锁的释放

    • 确保锁的及时释放
    • 使用try-finally结构
    • 避免锁泄露
  2. 超时设置

    • 过期时间要大于业务执行时间
    • 合理设置获取锁超时时间
    • 避免死锁情况

🔍 常见问题

  1. 锁无法获取

    • 检查Redis连接状态
    • 验证锁key是否正确
    • 确认超时时间设置
  2. 锁释放失败

    • 检查锁是否已过期
    • 验证释放锁的方法调用
    • 查看Redis日志