Redisson分布式锁的配置和使用

时间:2025-03-22 07:20:21

基于springBoot的redisson分布式锁

之前使用Redis分布式锁都是自己写的工具类,利用Redis的setNX特性;后来发现Redisson提供的分布式锁是真的好用。
Redisson可以看做是对Redis的一个操作工具类。将原生的RedisHash,List,Set,String等数据结构封装为Java里大家最熟悉的映射(Map),列表(List),集(Set)等。

Redisson集成SpringBoot主要有两种方式:

一个是使用redisson-spring-boot-starter依赖,然后在配置文件中写上Redis的配置信息即可,具体参考这篇文章/Muscleheng/article/details/139248641 推荐 推荐。

再一种方式就是引入redisson原始依赖,自己写配置类注入到spring容器中,这里就使用这种方式。

一、配置文件

        文件添加依赖

        <dependency>
            <groupId></groupId>
            <artifactId>redisson</artifactId>
            <version>3.16.1</version>
        </dependency>

        配置文件配置

spring
  redis:
    database: 0
    host: 1.1.1.1
    port: 6379
    password: 123456
#集群模式时使用
    cluster:
      nodes: 1.1.1.1:6379, 1.1.1.1:6379, 1.1.1.1:6379, 1.1.1.1:6379, 1.1.1.1:6379

二、RedisTemplate序列化配置

    // 配置序列化
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        (1);
        (new StringRedisSerializer());
        (new GenericJackson2JsonRedisSerializer());
        (redisConnectionFactory);
        return template;
    }

三、RedissonConfig配置

@ConfigurationProperties(prefix = "")
@Component
@Data
public class RedissonConfig {

    // 读取配置文件里面的Redis信息
    private String password;
    private Cluster cluster;
    public static class Cluster {
        private List<String> nodes;
        public List<String> getNodes() {
            return nodes;
        }
        public void setNodes(List<String> nodes) {
             = nodes;
        }
    }

    /**
     * 配置redisson
     * @return
     */
    @Bean
    public Redisson redisson() {
        List<String> clusterNodes = new ArrayList<>();
        for (int i = 0; i < ().getNodes().size(); i++) {
            ("redis://" + ().getNodes().get(i));
        }
        Config config = new Config();
        ClusterServersConfig clusterServersConfig = ()
                .addNodeAddress((new String[()]));
        (getPassword());
        return (Redisson) (config);
    }

}

四、编写RedissonUtil工具类

@Component
public class RedissonUtil {
    private static final Logger logger = ();
    /**
     * redis锁前缀
     */
    public static final String SYS_LOCK_FLAG = "MY_LOCK";

    /**
     * 用于隔开缓存前缀与缓存键值
     */
    public static final String KEY_SPLIT = ":";
    
    // 静态属性注入
    private static Redisson redisson;
    @Autowired
    public void setRedisson(Redisson redisson) {
         = redisson;
    }

    /**
     * 加锁,一直等待直到获得锁为止,不建议使用
     *
     * @param lockName    锁名  相同的key表示相同的锁,建议针对不同的业务使用不同的key
     * @param expiresTime 过期时间,单位:秒
     * @return
     */
    public static boolean getLock(String lockName, long expiresTime) {
        String key = getLockKey(lockName);
        //获取锁对象
        RLock lock = (key);
        //设置锁过期时间,防止死锁的产生
        (expiresTime, );
        ("获取锁成功,Redis Lock key :{}", key);
        return true;
    }


    /**
     * 加锁,规定时间内没抢到锁就放弃
     *
     * @param lockName    锁名  相同的key表示相同的锁,建议针对不同的业务使用不同的key
     * @param waitTime    最大等待锁时间
     * @param expiresTime 锁过期时间,单位:秒
     * @return
     * @throws InterruptedException
     */
    public static boolean getTryLock(String lockName, long waitTime, long expiresTime) {
        String key = getLockKey(lockName);
        //获取锁对象
        RLock lock = (key);
        //设置锁过期时间,防止死锁的产生
        boolean lockFlag = false;
        try {
            lockFlag = (waitTime, expiresTime, );
        } catch (InterruptedException e) {
            ("加锁出现异常", e);
        } finally {
            if (lockFlag) {
                unlock(lockName);
            }
        }
        String msg = "获取锁失败";
        if (lockFlag) {
            msg = "获取锁成功";
        }
        ("{},Redis Lock key :{}", msg, key);
        return lockFlag;
    }



    /**
     * 释放锁,建议放在 finally里面
     *
     * @param lockName 锁名称
     */
    public static void unlock(String lockName) {
        String key = getLockKey(lockName);
        //获取所对象
        RLock lock = (key);
        // 释放锁,判断要解锁的key是否已被锁定并且是否被当前线程保持
        if (() && ()) {
            ();
            ("释放Redis锁成功,key:{}", key);
        }
    }

    /**
     * 对锁的key添加系统标识前缀
     *
     * @return
     */
    private static String getLockKey(String key) {
        return RedissonUtil.SYS_LOCK_FLAG + RedissonUtil.KEY_SPLIT + key;
    }

}

五、使用

    @Test
    public void redissonLock(){
        String key = "zhh11";
        long waitTime = 10;
        long expiresTime = 10;
        // 加锁
        if ((key, waitTime, expiresTime)){
            try{
                (3000L);
                // 业务代码
            }catch (Exception e){
                ();
            }finally {
                // 释放锁
                (key);
                // 捕获异常之后需要 手动回滚事务
                //    ().setRollbackOnly();
            }
        }else {
            ("未获取到锁");
        }
    }