生产可用的 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. 代码可直接复制到生产环境使用,无坑、稳定可靠
相关推荐
robottt66619 分钟前
2026国产协作机器人排名与选型指南:越疆、遨博、节卡、珞石解析
大数据·数据库·人工智能
郑州光合科技余经理28 分钟前
本地生活系统:多业务订单字段怎么分账本导出
java·开发语言·前端·数据库·uni-app·php·ai编程
weixin_460443563 小时前
考试监控大屏为什么不能直接查数据库?WebSocket、Redis与实时数据聚合架构设计
数据库·redis·在线考试系统·培训考试系统·煤矿培训考试系统·煤矿在线考试系统·宏远培训考试系统
风哥2号3 小时前
数据库教程FGMT02‑生产环境Linux+Oracle19c安装配置与项目实战
linux·数据库·ffmpeg
九皇叔叔8 小时前
【第二章】Redis基础入门:Redis是什么、为什么快以及核心特性详解
数据库·redis·缓存
云和恩墨8 小时前
删库不跑路,回滚极速触达——zData S“旁路日志”持续保护原理深剖
数据库
MetaLite8 小时前
SpringBoot接口分层规范-外网网关内部服务与参数边界
java·数据库·spring boot
Wang's Blog10 小时前
Java框架快速入门: Spring Security+OAuth2之元注解简化权限表达式
java·数据库·spring
木圭的AI时代指南11 小时前
Spark-X2.5 长输入 Agent 实测:全量读取陷阱与解释器寻找死循环复盘,附可复现任务
大数据·分布式·spark
蓝速科技12 小时前
医院导诊 AI 数字人一体机场景适配与落地指南丨蓝速科技
运维·数据库·人工智能·科技·自然语言处理·技术分享