一、引入MAVEN依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.3.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.16.4</version>
        </dependency>

二、application.yaml配置

redisson:
  server:
    # 单机:stand-alone
    host: 101.43.201.38
    port: 6379
    database: 0
    type: stand-alone
  #     哨兵:sentinel ;主从: 或者 master-slave  集群:cluster
  #        master: mymaster
  #        nodes: 172.16.39.18:26376,172.16.39.18:26377,172.16.39.18:26378
  #        password: csp172@eb5g
  #        database: 0
  #        type: sentinel
  #     集群:cluster
  #    nodes: 172.16.39.18:26376,172.16.39.18:26377,172.16.39.18:26378
  #    password: csp172@eb5g
  #    database: 0
  #    type: cluster
  #获取锁最长等待时间,单位秒
  waitTime: 10
  #锁过期最长时间,单位秒
  leaseTime: 10

添加配置类

package com.microservice.stock.config;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @author zzkk
 * @desc redisson配置,
 * 如需使用,
 * 请将配置加入到spring容器 ,放开@Component 、 @ConfigurationProperties,
 * 并在yaml中添加配置
 * @date 2022/9/22 10:39
 */
@Component
@ConfigurationProperties(prefix = "redisson.server")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RedissonProperties {
    /**
     * redis主机地址
     */
    private String host;

    /**
     * PORT
     */
    private String port;

    /**
     * 连接类型,支持stand-alone-单机节点,sentinel-哨兵,cluster-集群,master-slave-主从
     */
    private String type;

    /**
     * redis 连接密码
     */
    private String password;

    /**
     * 选取那个数据库
     */
    private String database;

    /**
     * 节点信息
     */
    private String nodes;

    /**
     * 主节点
     */
    private String master;

    public RedissonProperties setPassword(String password) {
        this.password = password;
        return this;
    }

    public RedissonProperties setDatabase(String database) {
        this.database = database;
        return this;
    }


}

RedissionClient

package com.microservice.stock.config;

import com.microservice.stock.utils.redisson.StandAlone;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RedissonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author zzkk
 * @desc RedissionConfig
 * @date 2022/9/22 10:27
 */
@Configuration
@RequiredArgsConstructor
public class RedissonConfig {

    private final RedissonProperties redissonProperties;

    @Bean
    public RedissonClient getRedisson() {
        return StandAlone.getInstance(redissonProperties);
    }
}

单机

package com.microservice.stock.utils.redisson;

import com.microservice.stock.config.RedissonProperties;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.util.StringUtils;

/**
 * @author zzkk
 * @desc 单机
 * @date 2022/9/22 11:06
 */
public class StandAlone {

    public static volatile RedissonClient standAloneClient = null;

    public static synchronized RedissonClient getInstance(RedissonProperties redissonProperties) {

        String type = "stand-alone";

        if (!type.equalsIgnoreCase(redissonProperties.getType().trim())) {
            return Sentinel.getInstance(redissonProperties);
        }
        //实例没创建,才会进入内部的 synchronized 代码块,提高性能,防止每次都加锁
        if (standAloneClient == null) {
            //可能第一个线程在synchronized 代码块还没创建完对象时,第二个线程已经到了这一步,所以里面还需要加上判断
            synchronized (StandAlone.class) {
                //也许有其他线程已经创建实例,所以再判断一次
                if (standAloneClient == null) {

                    Config config = new Config();

                    SingleServerConfig singleServerConfig = config.useSingleServer()
                            .setAddress("redis://" + redissonProperties.getHost() + ":" + redissonProperties.getPort());

                    if (StringUtils.hasText(redissonProperties.getPassword())) {
                        singleServerConfig.setPassword(redissonProperties.getPassword());
                    }
                    if (StringUtils.hasText(redissonProperties.getDatabase())) {
                        singleServerConfig.setDatabase(Integer.parseInt(redissonProperties.getDatabase()));
                    }

                    standAloneClient = Redisson.create(config);
                }
            }
        }
        return standAloneClient;
    }
}

主从

package com.microservice.stock.utils.redisson;

import com.microservice.stock.config.RedissonProperties;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.MasterSlaveServersConfig;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.Set;

/**
 * @author zzkk
 * @desc 主从
 * @date 2022/9/22 14:33
 */
public class MasterSlave {

    public static volatile RedissonClient masterSlaveClient = null;

    public static synchronized RedissonClient getInstance(RedissonProperties redissonProperties) {

        String type = "master-slave";

        if (!type.equalsIgnoreCase(redissonProperties.getType())) {

            return Cluster.getInstance(redissonProperties);
        }
        if (masterSlaveClient == null) {

            synchronized (MasterSlave.class) {

                if (masterSlaveClient == null) {

                    Config config = new Config();

                    String[] adds = redissonProperties.getNodes().split(",");

                    Set<String> nodeAddress = new HashSet<>();

                    for (int i = 0; i < adds.length; i++) {

                        StringBuilder stringBuilder = new StringBuilder("redis://");

                        adds[i] = stringBuilder.append(adds[i]).toString();

                        nodeAddress.add(adds[i]);

                    }
                    MasterSlaveServersConfig masterSlaveServersConfig = config.useMasterSlaveServers().setMasterAddress(adds[0]);

                    masterSlaveServersConfig.setSlaveAddresses(nodeAddress);

                    if (org.springframework.util.StringUtils.hasText(redissonProperties.getPassword())) {
                        masterSlaveServersConfig.setPassword(redissonProperties.getPassword());
                    }
                    if (StringUtils.hasText(redissonProperties.getDatabase())) {
                        masterSlaveServersConfig.setDatabase(Integer.parseInt(redissonProperties.getDatabase()));
                    }
                    masterSlaveClient = Redisson.create(config);
                }
            }
        }
        return masterSlaveClient;
    }
}

哨兵

package com.microservice.stock.utils.redisson;

import com.microservice.stock.config.RedissonProperties;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SentinelServersConfig;
import org.springframework.util.StringUtils;

/**
 * @author zzkk
 * @desc 哨兵
 * @date 2022/9/22 11:06
 */
public class Sentinel {

    public static volatile RedissonClient sentinelClient = null;

    public static synchronized RedissonClient getInstance(RedissonProperties redissonProperties) {

        String type = "sentinel";

        if (!type.equalsIgnoreCase(redissonProperties.getType())) {
            return Cluster.getInstance(redissonProperties);
        }
        if (sentinelClient == null) {

            synchronized (Sentinel.class) {

                if (sentinelClient == null) {

                    Config config = new Config();

                    String[] adds = redissonProperties.getNodes().split(",");

                    for (int i = 0; i < adds.length; i++) {

                        StringBuilder stringBuilder = new StringBuilder("redis://");

                        adds[i] = stringBuilder.append(adds[i]).toString();
                    }
                    SentinelServersConfig serverConfig = config.useSentinelServers()
                            .addSentinelAddress(adds)
                            .setMasterName(redissonProperties.getMaster());

                    if (org.springframework.util.StringUtils.hasText(redissonProperties.getPassword())) {
                        serverConfig.setSentinelPassword(redissonProperties.getPassword());
                    }
                    if (StringUtils.hasText(redissonProperties.getDatabase())) {
                        serverConfig.setDatabase(Integer.parseInt(redissonProperties.getDatabase()));
                    }
                    sentinelClient = Redisson.create(config);
                }
            }
        }
        return sentinelClient;
    }
}

集群

package com.microservice.stock.utils.redisson;

import com.microservice.stock.config.RedissonProperties;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.springframework.util.StringUtils;

/**
 * @author zzkk
 * @desc 集群
 * @date 2022/9/22 11:06
 */
public class Cluster {

    public static volatile RedissonClient clusterClient = null;

    public static synchronized RedissonClient getInstance(RedissonProperties redissonProperties) {

        String type = "cluster";

        if (!type.equalsIgnoreCase(redissonProperties.getType().trim())) {
            return MasterSlave.getInstance(redissonProperties);
        }

        if (clusterClient == null) {

            synchronized (Cluster.class) {

                if (clusterClient == null) {

                    String[] nodesList = redissonProperties.getNodes().split(",");

                    for (int i = 0; i < nodesList.length; i++) {

                        StringBuilder stringBuilder = new StringBuilder("redis://");

                        nodesList[i] = stringBuilder.append(nodesList[i]).toString();
                    }
                    Config config = new Config();

                    ClusterServersConfig clusterServersConfig = config.useClusterServers().addNodeAddress(nodesList);

                    if (StringUtils.hasText(redissonProperties.getPassword())) {
                        clusterServersConfig.setPassword(redissonProperties.getPassword());
                    }

                    clusterClient = Redisson.create(config);
                }
            }
        }
        return clusterClient;
    }
}

测试

    @Resource
    RedissonClient redissonClient;

    @Test
    public void redissionTest() throws InterruptedException {

        StopWatch stopWatch = new StopWatch();

        stopWatch.start("redission休眠看门口狗续约测试");

        final String lockKey = "my_redission_key";

        final RLock lock = redissonClient.getLock(lockKey);

        if (lock.tryLock()) {
            try {
                System.out.println("加锁成功,等待观察redis过期时间是否自动续期");

                TimeUnit.SECONDS.sleep(60);

                System.out.println("休眠结束");
            } finally {
                if (lock.isLocked() && lock.isHeldByCurrentThread()) {

                    System.out.println("释放当前执行线程的锁");

                    lock.unlock();
                }
                System.out.println("解锁成功");
            }
        }
        stopWatch.stop();

        System.out.println(stopWatch.prettyPrint());
    }

tryLock方法注意事项:


        //  1、lock.tryLock(2, 40, TimeUnit.SECONDS) 自定义最大加锁时长,看门狗续约会失效;
        //     可能发生加锁代码未执行完成,但锁已经过期,出现解锁异常,
        //     或者解锁到其他线程加的锁(可以用lock.isHeldByCurrentThread()检查锁是否被当前线程持有);所以不建议使用自定义有效期
        //  2、lock.tryLock(),使用看门狗自动续约机制(每隔10秒自动续约,默认30秒)
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐