生产可用的 Redis 分布式锁完整实现

Redis 分布式锁是分布式系统中解决并发安全 的核心方案,生产环境绝对不能用简单的 SETNX ,必须满足:加锁原子性、防死锁、防误删、可重入、高可用

我会给你可直接落地生产的 Java 实现(Redisson 最佳实践) + 核心原理 + 避坑指南


一、生产级 Redis 分布式锁核心要求

  1. 互斥性:同一时间只有一个客户端持有锁
  2. 防死锁:客户端宕机也能自动释放锁(必须设置过期时间)
  3. 原子性:加锁 + 设置过期必须是原子操作
  4. 防误删:只能删除自己加的锁,不能删除别人的
  5. 可重入:同一个线程/客户端可重复加锁(避免死锁)
  6. 高可用:Redis 集群/主从下依然可靠
  7. 容错性:锁等待、重试、超时机制

二、绝对不要用的错误实现

以下写法生产环境必出问题,严禁使用:

java 复制代码
// 错误1:加锁和过期时间非原子,客户端宕机直接死锁
redis.setnx(key, value);
redis.expire(key, 30);

// 错误2:没有唯一标识,会误删别人的锁
redis.del(key);

// 错误3:判断和删除非原子,并发下依然误删
if (redis.get(key).equals(value)) {
    redis.del(key); // 这里锁已过期,会删别人的锁
}

三、生产标准实现:基于 Redisson(推荐)

Redisson 是 Redis 官方推荐的分布式锁框架,完美实现了所有生产特性:

  • 原子加锁/解锁
  • 锁自动续期(看门狗机制)
  • 可重入锁
  • 公平锁/读写锁
  • 红锁(解决 Redis 主从切换锁丢失问题)
  • 支持集群、哨兵、单机模式

1. 依赖引入(Maven)

xml 复制代码
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.29.0</version> <!-- 稳定版 -->
</dependency>

2. Redisson 配置(application.yml)

yaml 复制代码
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: your-password
    database: 0

3. 生产可用工具类

java 复制代码
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 生产级 Redis 分布式锁工具类(基于 Redisson)
 */
@Component
public class RedisDistributedLock {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 加锁
     * @param lockKey 锁key
     * @param waitTime 等待获取锁的时间
     * @param leaseTime 锁自动释放时间(不传启用看门狗自动续期)
     * @return 是否加锁成功
     */
    public boolean lock(String lockKey, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            // 尝试加锁,最多等待waitTime,上锁后leaseTime秒自动解锁
            return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }

    /**
     * 解锁(仅自己的锁可解)
     */
    public void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        // 校验锁归属 + 解锁,原子操作
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}

4. 业务代码使用示例

java 复制代码
@Service
public class OrderService {

    @Resource
    private RedisDistributedLock distributedLock;

    public void createOrder(Long userId) {
        String lockKey = "order:lock:" + userId;
        // 等待3秒,锁10秒自动释放
        boolean lockSuccess = distributedLock.lock(lockKey, 3, 10);
        
        if (!lockSuccess) {
            throw new RuntimeException("请求太频繁,请稍后再试");
        }

        try {
            // 核心业务逻辑(扣库存、创建订单...)
            System.out.println("获取锁成功,执行业务");
        } finally {
            // 必须在 finally 中解锁
            distributedLock.unlock(lockKey);
        }
    }
}

四、核心生产特性详解

1. 看门狗自动续期(避免业务未执行完锁过期)

  • 如果不指定 leaseTime ,Redisson 会启用看门狗
  • 默认每 30s 检查一次,只要线程没释放,就自动延长锁时间
  • 彻底解决:业务执行时间 > 锁过期时间导致的锁失效问题

2. 防误删原理

  • 每个锁携带唯一客户端ID + 线程ID
  • 解锁时校验:只有自己的锁才能解锁
  • 解锁是 Lua 脚本原子操作,无并发安全问题

3. 可重入锁原理

  • 锁内部维护计数器,同一线程重复加锁计数+1,解锁计数-1
  • 计数为0时真正释放锁
  • 避免同一线程重复加锁导致死锁

五、高可用终极方案:Redlock 红锁

适用场景

金融、支付等绝对不允许锁丢失的核心业务(解决 Redis 主从切换锁丢失问题)

原理

  • N 个独立 Redis 节点(无主从)申请锁
  • 超过半数节点加锁成功,才算加锁成功
  • 解锁时向所有节点解锁

实现

java 复制代码
// 红锁使用(多独立Redis节点)
RLock lock1 = redissonClient1.getLock(key);
RLock lock2 = redissonClient2.getLock(key);
RLock lock3 = redissonClient3.getLock(key);
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
redLock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);

六、生产环境最佳实践

  1. 锁粒度尽可能小:只锁核心资源,提升并发性能
  2. 必须设置等待时间:避免无限阻塞
  3. 解锁必须放在 finally:保证无论如何都释放锁
  4. 核心业务用红锁:普通业务用普通分布式锁
  5. 监控锁竞争:添加日志、监控,排查锁等待、死锁问题
  6. 避免长业务持有锁:锁内只做原子操作,不做远程调用/慢查询

总结

  1. 生产环境必须用 Redisson,不要手写 Redis 锁
  2. 核心保障:原子加锁、唯一标识、Lua 解锁、看门狗续期、可重入
  3. 高可用:普通业务用普通锁,核心业务用 Redlock 红锁
  4. 代码可直接复制到生产环境使用,无坑、稳定可靠
相关推荐
小饼干在学嘎瓦1 小时前
秒杀场景Redis做预扣减,问题在哪里?
数据库·redis·mybatis
咸鱼翻身小阿橙1 小时前
文件读写 + Qt Model/View + 自定义分页+搜索过滤
java·数据库·qt
l1t1 小时前
DeepSeek总结的DuckDB-Iceberg 在 v1.5.3 中的新特性
数据库·duckdb
Database_Cool_1 小时前
数据仓库弹性扩缩容怎么实现?阿里云 AnalyticDB MySQL Serverless 弹性架构详解
数据库·人工智能·阿里云
abcy0712131 小时前
django聚合函数
数据库·sqlite
念越1 小时前
数据库系统概论第6版王珊版:第二章关系代数与第三章SQL期末重点整理
数据库·sql·性能优化
TDengine (老段)1 小时前
TDengine 数据保留与 TTL — 多级存储、过期删除与分层迁移
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
安当加密03011 小时前
等保2.0三级数据库加密:2026检查清单 + TDE部署实战(附脚本)
数据库·网络安全·数据安全·tde·等保2.0·数据库加密·tde透明加密
解决问题no解决代码问题1 小时前
TiDB 原理与节点宕机实战讲解
数据库·tidb