Redisson分布式锁的配置和使用

基于springBoot的redisson分布式锁

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

我的项目中使用了RedisTemplate,现在要在此基础上使用Redisson,如果再在配置文件里面添加一份Redisson的配置,那维护起来就非常麻烦,如果改动了配置信息,就要改动两个地方的配置。所以写一个RedissonConfig配置类,在配置里面读取RedisTemplate的配置信息即可;

一、配置文件

        1.pom文件添加依赖

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

        2.yml配置文件配置

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<>();
        redisConnectionFactory.setDatabase(1);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

三、RedissonConfig配置

@ConfigurationProperties(prefix = "spring.redis")
@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) {
            this.nodes = nodes;
        }
    }

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

}

四、编写RedissonUtil工具类

@Component
public class RedissonUtil {
    private static final Logger logger = LoggerFactory.getLogger(RedissonUtil.class);
    /**
     * 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) {
        RedissonUtil.redisson = redisson;
    }

    /**
     * 加锁,一直等待直到获得锁为止,不建议使用
     *
     * @param lockName    锁名  相同的key表示相同的锁,建议针对不同的业务使用不同的key
     * @param expiresTime 过期时间,单位:秒
     * @return
     */
    public static boolean getLock(String lockName, long expiresTime) {
        String key = getLockKey(lockName);
        //获取锁对象
        RLock lock = redisson.getLock(key);
        //设置锁过期时间,防止死锁的产生
        lock.lock(expiresTime, TimeUnit.SECONDS);
        logger.info("获取锁成功,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 = redisson.getLock(key);
        //设置锁过期时间,防止死锁的产生
        boolean lockFlag = false;
        try {
            lockFlag = lock.tryLock(waitTime, expiresTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            logger.error("加锁出现异常", e);
        } finally {
            if (lockFlag) {
                unlock(lockName);
            }
        }
        String msg = "获取锁失败";
        if (lockFlag) {
            msg = "获取锁成功";
        }
        logger.info("{},Redis Lock key :{}", msg, key);
        return lockFlag;
    }



    /**
     * 释放锁,建议放在 finally里面
     *
     * @param lockName 锁名称
     */
    public static void unlock(String lockName) {
        String key = getLockKey(lockName);
        //获取所对象
        RLock lock = redisson.getLock(key);
        // 释放锁,判断要解锁的key是否已被锁定并且是否被当前线程保持
        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
            lock.unlock();
            logger.info("释放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 (RedissonUtil.getTryLock(key, waitTime, expiresTime)){
            try{
                Thread.sleep(3000L);
                // 业务代码
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                // 释放锁
                RedissonUtil.unlock(key);
                // 捕获异常之后需要 手动回滚事务
                //    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }
        }else {
            System.out.println("未获取到锁");
        }
    }

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Redisson是一个基于Redis实现的Java驻内存数据网格(In-Memory Data Grid)和分布式锁(Distributed Lock)框架,它提供了一系列的分布式数据结构,其中包括分布式锁的实现。 使用Redisson实现分布式锁非常简单,只需要遵循以下步骤: 1. 引入Redisson的依赖包: ```xml <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.12.6</version> </dependency> ``` 2. 创建Redisson客户端对象: ```java Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redisson = Redisson.create(config); ``` 3. 获取锁对象: ```java RLock lock = redisson.getLock("myLock"); ``` 4. 加锁: ```java lock.lock(); ``` 5. 执行业务逻辑: ```java try { // 执行业务逻辑 } finally { // 释放锁 lock.unlock(); } ``` 完整的示例代码如下: ```java public class MyService { private RedissonClient redisson; public MyService() { Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); redisson = Redisson.create(config); } public void myMethod() { RLock lock = redisson.getLock("myLock"); try { lock.lock(); // 执行业务逻辑 } finally { lock.unlock(); } } } ``` 需要注意的是,在执行业务逻辑的过程中,一定要放在try...finally块中,并在finally块中释放锁,以确保在出现异常时锁能够正确地被释放。 ### 回答2: Redisson是一种基于Redis实现的分布式锁框架。以下是Redisson分布式锁使用说明: 1. 引入Redisson依赖:首先需要在项目中引入Redisson的依赖,可以通过Maven或者Gradle等构建工具来管理依赖。 2. 创建RedissonClient:使用RedissonClient可以连接到Redis服务器,并获取一个分布式锁对象。 3. 加锁:使用分布式锁对象可以通过lock()方法来获取锁,该方法默认的锁超时时间是30秒,超过该时间锁会自动释放。也可以使用自定义的锁超时时间。 4. 解锁:在加锁的代码块执行完毕后,需要调用unlock()方法手动释放锁,确保锁的释放,避免死锁的产生。 5. 锁的可重入性:Redisson分布式锁支持可重入性,即同一个线程可以多次获取同一个锁,在释放锁的时候需要调用相应次数的unlock()方法来释放锁。 6. 锁的异步执行:Redisson分布式锁也支持异步执行,即lock()方法可以通过异步方式获取锁。 7. 锁的公平性:Redisson分布式锁可以选择是否公平锁,默认为非公平锁,即不保障获取锁的顺序。可以通过配置参数来设置公平锁。 8. 锁监控:Redisson提供了监控分布式锁的功能,可以通过调用getLock("/lock")方法来监控名为"lock"的锁的情况。 总结来说,Redisson分布式锁使用非常简单,只需要引入依赖、创建客户端、加锁和解锁即可。同时,Redisson还提供了可重入性、异步执行、公平锁和锁监控等功能,可以根据实际需求进行配置使用。通过使用Redisson分布式锁,可以有效地控制多线程环境下共享资源的访问,避免数据不一致和竞态条件的发生。 ### 回答3: Redisson是一个基于Redis的Java实现,提供了一系列分布式相关的功能,其中包括分布式锁使用使用Redisson实现分布式锁,首先需要创建一个RedissonClient实例,通过该实例可以获取一个RLock对象,RLock提供了加锁和释放锁的方法。 在加锁方面,Redisson支持公平锁和非公平锁。公平锁会按照请求的顺序依次加锁,而非公平锁则允许插队,谁先抢到锁就谁先执行。通过调用RLock对象的lock()方法可以获取锁,该方法会一直阻塞直到获取到锁为止。如果不希望一直阻塞,可以使用tryLock()方法,该方法会尝试获取锁一段时间,如果超过指定的等待时间仍未获取到锁,则返回false。 在释放锁方面,可以使用unlock()方法来释放锁,只有加锁方才能释放锁。可以通过判断当前线程是否持有锁,再决定是否释放锁。 使用Redisson分布式锁还有一些其他的特性,比如锁的自动续约、可重入锁、可中断锁等,这些特性都可以通过相应的方法来使用。 总的来说,Redisson分布式锁使用起来非常方便,只需要简单的几行代码就可以实现分布式环境下的锁功能。但需要注意的是,在使用分布式锁时要考虑并发情况、死锁问题以及锁的粒度等,以确保代码的正确性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值