分布式锁之RedissonLock

本文详细介绍了Redisson的看门狗机制在分布式锁中的应用,包括配置参数、YAML文件设置以及如何使用RedissonClient实现分布式锁功能。还展示了RedissonProperties和DistributedLock接口的实现与使用示例。
摘要由CSDN通过智能技术生成

什么是Redisson?
俗话说他就是看门狗,看门狗机制是一种用于保持Redis连接活跃性的方法,通常用于分布式锁的场景。看门狗的工作原理是:当客户端获取到锁之后,会对Redis中的一个特定的键设置一个有限的过期时间,然后每隔一段时间(默认是15秒),客户端会对这个键“续约”,即重新设置它的过期时间,以此来保持锁的持有状态,防止锁因为某些原因(如客户端崩溃或网络问题)而被释放。
在这里插入图片描述
以下是核心实战部分
配置文件读取

@ConfigurationProperties(
        prefix = "spring.redis.redisson"
)
@Data
public class RedissonProperties {

    /**
     * key前缀
     */
    private String keyPrefix;

    /**
     * 拿锁等待时间(毫秒)
     */
    private long waitTime = 10000;

    /**
     * 默认ttl时间(毫秒)
     */
    private long leaseTime = 60000;

    @Value("${spring.redis.redisson.config.clusterServersConfig.nodeAddresses}")
    private String nodeAddresses;

    @Value("${spring.redis.redisson.config.clusterServersConfig.scanInterval}")
    private Integer scanInterval;

    @Value("${spring.redis.redisson.config.threads}")
    private Integer threads;

    @Value("${spring.redis.redisson.config.nettyThreads}")
    private Integer nettyThreads;

    @Value("${spring.redis.redisson.config.transportMode}")
    private String transportMode;
}

yml文件

spring:
  ##redis集群配置
  redis:
    database: 0
    timeout: 5000ms
    redisson:
      config:
        clusterServersConfig:
          nodeAddresses: redis://10.xxx.xx.x1:6379,redis://10.xxx.xx.x2:6379,redis://10.xxx.xx.x3:6379
          scanInterval: 1000
        nettyThreads: 0
        threads: 0
        transportMode: NIO
      key-prefix: test:key
      lease-time: 80000
      wait-time: 50000

redisson自动配置类

@Configuration
@ConditionalOnClass({Redisson.class})
@EnableConfigurationProperties({RedissonProperties.class})
@Slf4j
public class RedissonAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean({RedisConnectionFactory.class})
    public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
        return new RedissonConnectionFactory(redisson);
    }

    @Bean(
            destroyMethod = "shutdown"
    )
    @ConditionalOnMissingBean({RedissonClient.class})
    public RedissonClient redisson(RedissonProperties redissonProperties) throws IOException {
        Config config = new Config();
        config.useClusterServers().addNodeAddress(redissonProperties.getNodeAddresses().split(","))
                .setScanInterval(redissonProperties.getScanInterval());
        config.setThreads(redissonProperties.getThreads())
                .setNettyThreads(redissonProperties.getNettyThreads())
                .setTransportMode(TransportMode.valueOf(redissonProperties.getTransportMode()));
        return Redisson.create(config);
    }

    @Bean
    @ConditionalOnMissingBean(
            name = {"redisTemplate"}
    )
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

}

redis的缓存类实现

@Service
public class RedisCache {

	@Autowired
    private RedissonClient redisson;

	@Autowired
    private RedissonProperties redissonProperties;

	/**
     * 缓存
     *
     * @param key 缓存key
     * @param <T>
     * @return 缓存返回值
     */
    public <T> T get(String key) {
        RBucket<T> bucket = redisson.getBucket(getKey(key));
        return bucket.get();
    }

    /**
     * 以string的方式读取缓存
     *
     * @param key 缓存key
     * @return 缓存返回值
     */
    public String getString(String key) {
        RBucket<String> bucket = redisson.getBucket(getKey(key), StringCodec.INSTANCE);
        return bucket.get();
    }

    /**
     * 以string的方式保存缓存(与其他应用共用redis时需要使用该函数)
     *
     * @param key     缓存key
     * @param value   缓存值
     * @param expiredTime 缓存过期时间
     */
    public void putString(String key, String value, long expiredTime) {
        RBucket<String> bucket = redisson.getBucket(getKey(key), StringCodec.INSTANCE);
        bucket.set(value, expiredTime, TimeUnit.MILLISECONDS);
    }

    /**
     * 如果不存在则写入缓存(string方式,不带有redisson的格式信息)
     *
     * @param key     缓存key
     * @param value   缓存值
     * @param expiredTime 缓存过期时间
     */
    public boolean putStringIfAbsent(String key, String value, long expiredTime) {
        RBucket<String> bucket = redisson.getBucket(getKey(key), StringCodec.INSTANCE);
        return bucket.trySet(value, expiredTime, TimeUnit.MILLISECONDS);
    }


    /**
     * 设置缓存
     *
     * @param key     缓存key
     * @param value   缓存值
     * @param expiredTime 缓存过期时间
     * @param <T>     类型
     */
    public <T> void put(String key, T value, long expiredTime) {
        RBucket<T> bucket = redisson.getBucket(getKey(key));
        bucket.set(value, expiredTime, TimeUnit.MILLISECONDS);
    }

    /**
     * 如果不存在则设置缓存
     *
     * @param key     缓存key
     * @param value   缓存值
     * @param expiredTime 缓存过期时间
     * @param <T>     类型
     */
    public <T> void putIfAbsent(String key, T value, long expiredTime) {
        RBucket<T> bucket = redisson.getBucket(getKey(key));
        bucket.trySet(value, expiredTime, TimeUnit.MILLISECONDS);
    }

    /**
     * 移除缓存
     *
     * @param key
     */
    public void remove(String key) {
        redisson.getBucket(getKey(key)).delete();
    }

    /**
     * 判断缓存是否存在
     *
     * @param key
     * @return
     */
    public boolean exists(String key) {
        return redisson.getBucket(getKey(key)).isExists();
    }

    private String getKey(String key) {
    	return StringUtils.format("{0}:{1}", redissonProperties.getKeyPrefix(), key);
    }

获取和释放分布式锁接口
DistributedLock

/**
	 * get分布式锁
	 * @param lockKey
	 * @param requestId
	 * @param expireTime
	 * @return
	 */
	public boolean getDistributedLock(String lockKey, String requestId, long expireTime);
	
	/**
	 * remove分布式锁
	 * @param lockKey
	 * @param requestId
	 * @return
	 */
	public boolean removeDistributedLock(String lockKey, String requestId);

实现DistributedLock的实现类逻辑

@Service
public class RedisDistributedLocker implements DistributedLocker {
    private static final Logger logger = LoggerFactory.getLogger(RedisDistributedLocker.class);

    @Autowired
    private RedissonClient redisson;

    @Autowired
    private RedissonProperties redissonProperties;

 
    public boolean getDistributedLock(String lockKey, String flagId, long expireTime) {
        boolean success;
        try {
            if (expireTime == 0) {
                expireTime = redissonProperties.getLeaseTime();
            }
            lockKey = StringUtils.format("{0}:{1}", redissonProperties.getKeyPrefix(), lockKey);
            RLock locker = redisson.getLock(lockKey);
            success = locker.tryLock(redissonProperties.getWaitTime(), expireTime, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            success = false;
            logger.error(StringUtils.format("获取分布式锁失败,lockKey={0}, flagId={1}, expirTime={2}", lockKey, flagId, expireTime), e);
        }
        return success;
    }

    public boolean releaseDistributedLock(String lockKey, String flagId) {
        boolean success = false;
        try {
            lockKey = StringUtils.format("{0}:{1}", redissonProperties.getKeyPrefix(), lockKey);
            RLock locker = redisson.getLock(lockKey);
            if (locker.isHeldByCurrentThread()) {
                locker.unlock();
                success = true;
            }
        } catch (Exception e) {
            success = false;
            logger.error(StringUtils.format("分布式锁失败,lockKey={0}, flagId={1}", lockKey, flagId), e);
        }
        return success;
    }

在需要的业务场景下使用 以下为伪代码

try {
            boolean ock = distributedLocker.getDistributedLock(lockKey, flagId, 9000L);
            if (!ock) {
                return;
            }
            // 实现自己的业务逻辑。。。。。。。。。。。。。。。。。。。。。。。。。
			
        } catch (Exception e) {
            e.printStackTrace();
            
            throw new RuntimeException(e.getMessage());
        } finally {
            distributedLocker.releaseDistributedLock(lockKey, flagId);
        }

以上的是分布式锁之RedissonLock 若需完整代码 可识别二维码后 给您发代码。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值