首页 > 文章列表 > SpringBoot整合分布式锁redisson的示例代码

SpringBoot整合分布式锁redisson的示例代码

java
114 2023-03-17

1、导入maven坐标

<!-- 用redisson作为所有分布式锁,分布式对象等功能框架-->

    <dependency>

        <groupId>org.redisson</groupId>

        <artifactId>redisson</artifactId>

        <version>3.12.5</version>

    </dependency>

2、redisson配置类(如果redis没有密码就不需要private String password)

package com.xuechengpluscommon.config;

 

import org.redisson.Redisson;

import org.redisson.api.RedissonClient;

import org.redisson.config.Config;

import org.redisson.config.SingleServerConfig;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

 

/**

 * @description Redisson 配置类

 */

@Configuration

public class MyRedissonConfig {

 

    @Value(value = "${spring.redis.host}")

    private String host;

    @Value(value = "${spring.redis.port}")

    private int port;

    @Value(value = "${spring.redis.database}")

    private int database;

//    @Value(value = "${spring.redis.password}")

//    private String password;

 

    /**

     * 单Redis节点模式配置方法

     * 其他配置參數,看:

     * <a href = "https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95#26-%E5%8D%95redis%E8%8A%82%E7%82%B9%E6%A8%A1%E5%BC%8F">

     * 单Redis节点模式配置方法

     * </a>

     *

     * @return {@link RedissonClient}

     */

    @Bean(destroyMethod = "shutdown")

    RedissonClient redisson() {

        Config config = new Config();

        //Redis多节点

        // config.useClusterServers()

        //     .addNodeAddress("redis://127.0.0.1:6379", "redis://127.0.0.1:7001");

        //Redis单节点

        SingleServerConfig singleServerConfig = config.useSingleServer();

        //可以用"rediss://"来启用SSL连接

        String address = "redis://" + host + ":" + port;

        singleServerConfig.setAddress(address);

        //设置 数据库编号

        singleServerConfig.setDatabase(database);

//        singleServerConfig.setPassword(password);

        //连接池大小:默认值:64

        // singleServerConfig.setConnectionPoolSize()

        return Redisson.create(config);

    }

 

}

yml中redis的配置

redis:

    database: 0

    host: ip地址

    port: 6379

3、创建redisson的bean

@Autowired

private RedissonClient redisson;

4、测试,入队

@Test

void contextLoads1() {

    RQueue<String> queue = redisson.getQueue("RedissonQueue");

    queue.add("hello");

    System.out.println(queue);

}

redis数据

5、测试,出队

@Test

void contextLoads2() {

    RQueue<String> queue = redisson.getQueue("RedissonQueue");

    String remove = queue.remove();

    System.out.println(remove);

}

出队数据:

6、分布式锁

public R redisTest1() throws InterruptedException {

        //首先从redis查询数据

        Orders redisOrder;

        redisOrder=(Orders) redisTemplate.opsForValue().get("redisTest");

        //如果存在redis则返回

        if(ObjectUtils.isNotEmpty(redisOrder)){

            return R.ok(redisOrder);

            //如果不存在则从数据库查询

        }else {

            //首先获取分布式锁

            RLock lock = redissonClient.getLock("redisTestDogWatch");

            //上锁

            lock.lock();

 

            //获取锁之后进行查询

            try {

                redisOrder = (Orders) redisTemplate.opsForValue().get("redisTest");

                if (ObjectUtils.isNotEmpty(redisOrder)) {

                    return R.ok(redisOrder);

                }

                //数据库查询

                redisOrder= ordersService.getById(1577177773194113014L);

                redisTemplate.opsForValue().set("redisTest", redisOrder );

                System.out.println("[从数据库中查询]");

 

            } catch (Exception e) {

                e.printStackTrace();

            } finally {

                //删除锁

                lock.unlock();

            }

            return R.ok(redisOrder);

        }

    }

在这里让线程睡眠35秒

//上锁

lock.lock();

Thread.sleep(35000);

此时三个服务器运行

测试结果

可以首先看到已经上锁的redisTestDogWatch,每个锁30秒,如果线程未完成则会自动续30秒,如果线程完成到finally中的unlock就删除锁

目前可以看到只有一个服务器获取到锁

存储redis的数据

此时进行并发测试

依旧保持35秒的睡眠时间

此时可以看到未拿到锁的线程报错

java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: d904f2b9-e75d-472d-a5a6-d0a8cc603a80 thread-id: 210

尝试解锁锁定,未被当前线程锁定 按节点 ID:C731FAC4-9BF7-4F4A-ACC1-A2CC9B78A02F 线程 ID:232

这是因为锁住了,所以无法获取锁,然后看门狗会不断刷新