Skip to content

🚀基于Redis的分布式锁的介绍

✍️ 作者:桑榆
🕓 更新时间:2025-11-08 🧠 关键词: 基于Redis的分布式锁、介绍、实现、性能优化

🧩 前言

最近再学习shortlink短链接,当用户注册时,由于用户名是唯一的。 那么用户注册的时候,就需要判断用户名是否已经存在,如果存在了,那就不能注册。 但是紧接着就会有个问题,如果海量用户如果说查询的用户名存在或不存在,全部请求数据库,会将数据库直接打满。 这里就先使用布隆过滤器来判断用户名是否存在。 如果布隆过滤器判断用户名不存在,那么就可以继续注册,然后将用户名添加到布隆过滤器中。 如果布隆过滤器判断用户名存在,那么就不能注册。 如何防止恶意请求毫秒级触发大量请求去一个未注册的用户名?

这里可以使用Redis的分布式锁来防止恶意请求毫秒级触发大量请求去一个未注册的用户名。

二、代码示例

下面是项目中 UserServiceImpl 的核心逻辑,使用了 Redisson 实现 Redis 分布式锁,防止多个用户同时注册相同用户名。

java
RLock lock = redissonClient.getLock(LOCK_USER_REGISTER_KEY + requestParam.getUsername());
try {
    if (lock.tryLock()) {
        int insert = baseMapper.insert(BeanUtil.toBean(requestParam, UserDO.class));
        if (insert < 1) {
            throw new ClientException(UserErrorCodeEnum.USER_SAVE_ERROR);
        }
        userRegisterCachePenetrationBloomFilter.add(requestParam.getUsername());
        return;
    }
    throw new ClientException(UserErrorCodeEnum.USER_NAME_EXIT);
} finally {
    lock.unlock();
}

三、🔍 代码讲解

1. 获取分布式锁

java
RLock lock = redissonClient.getLock("LOCK_USER_REGISTER_KEY" + username);

Redisson 底层使用 Redis 来实现锁机制。每个用户名对应一个唯一的 Redis key。

2. 尝试加锁

java
if (lock.tryLock())
  • 只有第一个线程成功获取到锁,才能执行注册逻辑;
  • 其他线程会在未加锁时直接返回“用户名已存在”。

3. 执行业务逻辑

插入数据库用户信息,并通过布隆过滤器缓存用户名,防止缓存穿透。

4. 释放锁

java
lock.unlock();

确保无论是否发生异常,最终都能释放锁。

三、为什么要用分布式锁?

如果是单机部署,用 synchronizedReentrantLock 就够了;
但在 多台服务节点部署的分布式环境 下,这些锁是进程级别的,无法跨节点共享。

Redis 分布式锁的出现,就是为了解决这种跨节点的并发控制问题。

四、基于 Redis 的分布式锁原理

  1. 核心命令

    bash
    SET key value NX PX 30000
    • NX:仅当 key 不存在时才设置(防止重复上锁)
    • PX 30000:设置锁的过期时间(避免死锁)
  2. 解锁逻辑

    • 解锁前先判断锁是否属于自己,防止误删他人锁。
  3. Redisson 封装 Redisson 在此基础上扩展了:

    • 可重入锁(ReentrantLock)
    • 看门狗机制(自动续期锁)
    • 公平锁 / 读写锁 等高级特性

五、为什么配合布隆过滤器?

布隆过滤器(Bloom Filter)是用于防止缓存穿透的一种数据结构。
在注册逻辑中:

  • 先通过布隆过滤器判断用户名是否存在;
  • 再通过分布式锁控制注册并发。

两者结合,既防止重复注册,又提升性能。