首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Redis分布式锁,java程序员必备技能!

Redis分布式锁,java程序员必备技能!

作者头像
卡卡罗特AI
发布2026-09-10 08:43:19
发布2026-09-10 08:43:19
110
举报

戴嘎猴啊,我是程序员卡卡罗特~

在分布式系统架构中,随着业务规模的扩大,我们不可避免地会遇到多节点并发操作共享资源的问题。

在企业真实项目中,Redis分布式锁一般是怎么用的呢?

✿1、为什么需要Redis分布式锁?

单体应用中,我们可以用synchronizedReentrantLock等本地锁解决并发问题。

但当系统拆分为微服务,部署在多台服务器后,本地锁就失去了作用——因为不同服务器上的进程无法感知彼此的锁状态。

Redis分布式锁正是为解决这类跨服务器节点并发问题而生:

保证同一时间,只有一个服务器节点的一个进程能执行一段代码

防止因并发操作导致的数据不一致(如重复数据、数据错乱)

✿2、举个栗子

用Redis分布式锁解决用户重复注册问题

用户注册场景中,如果同一用户(比如同一手机号)在极短时间内提交多次注册请求,可能导致重复创建用户记录。

实际上,前端会做防抖校验,也是防止用户重复点击的,但是后端是必须要做的!因为万一前端没做呢?或者有人在你的网站通过代码调用注册接口呢🤔,emmm...

我们可以用Redis分布式锁来避免这种情况。

1. 分布式锁核心实现

这个类可以作为公共类使用

代码语言:javascript
复制
@Component
public class RedisDistributedLock {

    @Autowired
    private StringRedisTemplate redisTemplate;

    // 锁的过期时间(30秒),防止死锁
    private static final long LOCK_EXPIRE_MILLIS = 30000;
    // 尝试获取锁的超时时间(5秒)
    private static final long ACQUIRE_TIMEOUT_MILLIS = 5000;

    /**
     * 尝试获取分布式锁
     * @param lockKey 业务唯一标识(如手机号)
     * @return 锁的value(用于释放锁时的身份验证)
     */
    public boolean lock(String lockKey) {
        // SET NX PX:不存在则设置,同时设置过期时间
        return redisTemplate.opsForValue().setIfAbsent(lockKey, "1", Duration.ofMillis(LOCK_EXPIRE_MILLIS));
    }

    /**
     * 释放分布式锁
     * @param lockKey 业务唯一标识
     */
    public void unlock(String lockKey) {
        if (lockValue == null) {
            return;
        }

        redisTemplate.delete(lockKey);
    }
}

2. 在用户注册业务中使用

代码语言:javascript
复制
@Service
public class UserRegistrationService {

    @Autowired
    private RedisDistributedLock distributedLock;

    @Autowired
    private UserRepository userRepository;

    /**
     * 用户注册方法
     * @param phone 手机号(作为唯一标识)
     * @param userInfo 用户信息
     * @return 注册结果
     */
    public Result registerUser(String phone, UserInfo userInfo) {
        boolean locked = false;
        String lockKey = "USER_REGISTER_LOCK_" + phone;
        try {
            // 1、加锁失败,提前退出
            if (!distributedLock.lock(lockKey)) {
                return Result.fail("操作过于频繁,请稍后再试");
            }

            // 2. 检查用户是否已注册(临界区操作)
            User existingUser = userRepository.findByPhone(phone);
            if (existingUser != null) {
                return Result.fail("该手机号已注册");
            }

            // 3. 执行注册逻辑
            User newUser = new User();
            newUser.setPhone(phone);
            newUser.setUsername(userInfo.getUsername());
            // ... 设置其他用户信息
            userRepository.save(newUser);

            return Result.success("注册成功", newUser.getId());
        } finally {
            if (locked) {
                distributedLock.unlock(lockKey);
            }
        }
    }
}

重点

代码语言:javascript
复制
return redisTemplate.opsForValue().setIfAbsent(lockKey, "1", Duration.ofMillis(LOCK_EXPIRE_MILLIS));

核心是这段代码:当redis存在lockKey的时候,返回的是false。不存在的时候,返回的是true。

底层是依赖redis的set nx明了,来保证加锁的原子性。

✿总结

Redis分布式锁是解决分布式系统并发问题的重要工具,它通过Redis的单线程特性和原子命令,为跨节点的临界区操作提供了可靠的互斥保障。

在用户注册、商品秒杀、订单创建等核心场景中,合理使用分布式锁能有效避免数据不一致问题,保障系统的稳定性和数据准确性。

需要注意的是,Redis分布式锁在某些情况存在坑🤔,在实际使用中还需考虑Redis集群环境下的锁可靠性、锁过期时间设置等细节,这些我们会在后续文章中深入探讨。


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-11-02,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • ✿1、为什么需要Redis分布式锁?
  • ✿2、举个栗子
    • 1. 分布式锁核心实现
    • 2. 在用户注册业务中使用
    • 重点
  • ✿总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档