分布式互斥锁,基于Redis的SET NX命令

实现了一个基于 Redis 的分布式锁机制,包含获取锁和释放锁的逻辑。

1. 获取锁的逻辑:

private boolean tryLock(String key) {
    Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);
    // 避免返回值为null,这里使用了BooleanUtil工具类
    return BooleanUtil.isTrue(flag);
}

解析:

  • setIfAbsent 方法:

    • setIfAbsent 是 Spring Data Redis 提供的方法,底层对应 Redis 的 SET NX 命令。该方法的作用是:
      • 如果键 key 不存在,则将其设置为指定值(此处为 "1"),并设置过期时间(此处为 10 秒)。
      • 如果键已存在,则不执行任何操作。
    • 该方法返回一个 Boolean 对象:
      • 如果键不存在且设置成功,返回 true
      • 如果键已存在,返回 false
      • 在某些情况下,可能返回 null(例如,操作失败或出现异常)。
  • 使用 BooleanUtil.isTrue(flag)

    • 由于 setIfAbsent 方法可能返回 null,直接对其进行布尔判断可能导致 NullPointerException
    • BooleanUtil.isTrue(flag) 是一个工具方法,等价于 Boolean.TRUE.equals(flag),可以安全地判断 flag 是否为 true,避免空指针异常。

2. 释放锁的逻辑:

private void unlock(String key) {
    stringRedisTemplate.delete(key);
}

解析:

  • delete 方法:
    • delete 方法用于删除指定的键 key,对应 Redis 的 DEL 命令。
    • 调用此方法会直接删除 Redis 中的键,无论其是否存在。

注意事项:

  • 释放锁的安全性:
    • 在分布式环境中,释放锁时需要确保只有持有锁的线程或进程才能删除该锁,避免误删其他线程或进程的锁。
    • 一种常见的做法是在设置锁时,将一个唯一标识(如 UUID)作为值存入 Redis,释放锁时先获取 Redis 中的值,确认是自己设置的锁后再执行删除操作。

总结:

上述代码通过 setIfAbsent 方法尝试获取锁,并在获取成功后设置过期时间,以防止死锁。释放锁时,直接删除对应的键。

posted @ 2025-04-09 14:46  kuki'  阅读(29)  评论(0)    收藏  举报