栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

第三章 redis redisson实现分布式锁

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第三章 redis redisson实现分布式锁

上一章节 通过spring boot 集成了 redis ,本章在上一章的基础上集成 redisson,并实现分布式锁

1.在pom.xml 文件中加入 以下

	 
            org.redisson
            redisson
        

        
            com.alibaba
            fastjson
        

2.新建一个LockProperties 类,内容如下,并添加@ConfigurationProperties 注解,这个注解的作用就是让这个类可以读取到 配置信息,下面会有配置信息的类容

@Getter
@Setter
@ConfigurationProperties(LockProperties.PREFIX)
public class LockProperties {
    public static final String PREFIX = "study.lock";

    
    private Boolean enabled = Boolean.FALSE;
    
    private String address = "redis://127.0.0.1:6379";
    
    private String password;
    
    private Integer database = 0;
    
    private Integer poolSize = 20;
    
    private Integer idleSize = 5;
    
    private Integer idleTimeout = 60000;
    
    private Integer connectionTimeout = 3000;
    
    private Integer timeout = 10000;
    
    private Mode mode = Mode.single;
    
    private String masterAddress;
    
    private String[] slaveAddress;
    
    private String masterName;
    
    private String[] sentinelAddress;
    
    private String[] nodeAddress;

    public enum Mode {
        
        single,
        master,
        sentinel,
        cluster
    }
}

3.在application.yml 中加入 锁配置信息

#项目模块集中配置
study:
  #分布式锁配置
  lock:
    enabled: true
    address: redis://127.0.0.1:6379

4.定义LockAutoConfiguration.class

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;



@Configuration
@ConditionalOnClass(RedissonClient.class)
@EnableConfigurationProperties(LockProperties.class)
@ConditionalOnProperty(value = "study.lock.enabled", havingValue = "true")
public class LockAutoConfiguration {
    //单机模式
    private static Config singleConfig(LockProperties properties) {
        Config config = new Config();
        SingleServerConfig serversConfig = config.useSingleServer();
        serversConfig.setAddress(properties.getAddress());
        String password = properties.getPassword();
        if (!StringUtils.isEmpty(password)) {
            serversConfig.setPassword(password);
        }
        serversConfig.setDatabase(properties.getDatabase());
        serversConfig.setConnectionPoolSize(properties.getPoolSize());
        serversConfig.setConnectionMinimumIdleSize(properties.getIdleSize());
        serversConfig.setIdleConnectionTimeout(properties.getConnectionTimeout());
        serversConfig.setConnectTimeout(properties.getConnectionTimeout());
        serversConfig.setTimeout(properties.getTimeout());
        return config;
    }


    //主从模式
    private static Config masterSlaveConfig(LockProperties properties) {
        Config config = new Config();
        MasterSlaveServersConfig serversConfig = config.useMasterSlaveServers();
        serversConfig.setMasterAddress(properties.getMasterAddress());
        serversConfig.addSlaveAddress(properties.getSlaveAddress());
        String password = properties.getPassword();
        if (!StringUtils.isEmpty(password)) {
            serversConfig.setPassword(password);
        }
        serversConfig.setDatabase(properties.getDatabase());
        serversConfig.setMasterConnectionPoolSize(properties.getPoolSize());
        serversConfig.setMasterConnectionMinimumIdleSize(properties.getIdleSize());
        serversConfig.setSlaveConnectionPoolSize(properties.getPoolSize());
        serversConfig.setSlaveConnectionMinimumIdleSize(properties.getIdleSize());
        serversConfig.setIdleConnectionTimeout(properties.getConnectionTimeout());
        serversConfig.setConnectTimeout(properties.getConnectionTimeout());
        serversConfig.setTimeout(properties.getTimeout());
        return config;
    }

    //哨兵模式
    private static Config sentinelConfig(LockProperties properties) {
        Config config = new Config();
        SentinelServersConfig serversConfig = config.useSentinelServers();
        serversConfig.setMasterName(properties.getMasterName());
        serversConfig.addSentinelAddress(properties.getSentinelAddress());
        String password = properties.getPassword();
        if (!StringUtils.isEmpty(password)) {
            serversConfig.setPassword(password);
        }
        serversConfig.setDatabase(properties.getDatabase());
        serversConfig.setMasterConnectionPoolSize(properties.getPoolSize());
        serversConfig.setMasterConnectionMinimumIdleSize(properties.getIdleSize());
        serversConfig.setSlaveConnectionPoolSize(properties.getPoolSize());
        serversConfig.setSlaveConnectionMinimumIdleSize(properties.getIdleSize());
        serversConfig.setIdleConnectionTimeout(properties.getConnectionTimeout());
        serversConfig.setConnectTimeout(properties.getConnectionTimeout());
        serversConfig.setTimeout(properties.getTimeout());
        return config;
    }

    //集群模式
    private static Config clusterConfig(LockProperties properties) {
        Config config = new Config();
        ClusterServersConfig serversConfig = config.useClusterServers();
        serversConfig.addNodeAddress(properties.getNodeAddress());
        String password = properties.getPassword();
        if (!StringUtils.isEmpty(password)) {
            serversConfig.setPassword(password);
        }
        serversConfig.setMasterConnectionPoolSize(properties.getPoolSize());
        serversConfig.setMasterConnectionMinimumIdleSize(properties.getIdleSize());
        serversConfig.setSlaveConnectionPoolSize(properties.getPoolSize());
        serversConfig.setSlaveConnectionMinimumIdleSize(properties.getIdleSize());
        serversConfig.setIdleConnectionTimeout(properties.getConnectionTimeout());
        serversConfig.setConnectTimeout(properties.getConnectionTimeout());
        serversConfig.setTimeout(properties.getTimeout());
        return config;
    }



    @Bean
    @ConditionalOnMissingBean
    public RedisLockClient redisLockClient(LockProperties properties) {
        return new RedisLockClientImpl(redissonClient(properties));
    }


    private static RedissonClient redissonClient(LockProperties properties) {
        LockProperties.Mode mode = properties.getMode();
        Config config;
        switch (mode) {
            case sentinel:
                config = sentinelConfig(properties);
                break;
            case cluster:
                config = clusterConfig(properties);
                break;
            case master:
                config = masterSlaveConfig(properties);
                break;
            case single:
                config = singleConfig(properties);
                break;
            default:
                config = new Config();
                break;
        }
        return Redisson.create(config);
    }

}

5定义要实现的锁

public enum  LockType {
    
    REENTRANT,
    
    FAIR

}

6定义锁的API并实现

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
public interface RedisLockClient {

	//解锁
    void unLock(String lockName,LockType lockType);

	//加锁
     T lock(String lockName, LockType lockType, long waitTime, long leaseTime, TimeUnit timeUnit, Supplier supplier);
}




@Slf4j
@RequiredArgsConstructor
public class RedisLockClientImpl implements RedisLockClient {

    private final RedissonClient redissonClient;


    private RLock getLock(String lockName, LockType lockType) {
        RLock lock;
        if (LockType.REENTRANT == lockType) {
            lock = redissonClient.getLock(lockName);
        } else {
            lock = redissonClient.getFairLock(lockName);
        }
        return lock;
    }

    @Override
    public void unLock(String lockName, LockType lockType) {

        RLock lock = getLock(lockName, lockType);
        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
            lock.unlock();
        }

    }

    @Override
    public  T lock(String lockName, LockType lockType, long waitTime, long leaseTime, TimeUnit timeUnit, Supplier supplier) {
        try {
            RLock rLock = getLock(lockName, lockType);
            boolean result = rLock.tryLock(waitTime, leaseTime, timeUnit);
            if (result) {
                //rLock.lock(leaseTime, timeUnit);
                return supplier.get();
            } else {
                return (T) "获取锁失败";
            }
        } catch (Throwable e) {
            log.info("锁异常");
        } finally {
            this.unLock(lockName, lockType);
        }
        return null;
    }
}

7.编写代码测试

    @GetMapping("testLock")
    public String testRedissonLock() {
        Supplier checkedSupplier = () -> getServiceTest();
        //设置 等待上锁时间1s  设置失效时间100s
        String xx = redisLockClient.lock("xx", LockType.REENTRANT, 1, 100, TimeUnit.SECONDS, checkedSupplier);
        return xx;
    }

  // 虚拟的业务方法
    public String getServiceTest() {
        try {
            Thread.sleep(100000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
            return "OK";
    }

效果
第一次访问接口

第二次访问接口 100s之内

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/336577.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号