分布式锁之RedissonLock

什么是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 若需完整代码 可识别二维码后 给您发代码。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/596530.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

投资海外标的,首选跨境ETF!现在新开佣金低至万0.5!

全球资产配置的利器 随着经济的发展&#xff0c;全球资产配置成为中产阶级的关注方向。目前&#xff0c;全球资产配置的主要渠道包括直接开立境外账户、 QDII 基金、跨境 ETF 等。 现阶段通过跨境 ETF 投资境外股市是最便利、最具效率的方式之一。首先&#xff0c;与直接境外…

4. RedHat认证-进程管理

4. RedHat认证-进程管理 1.进程概念 进程就是正在运行中的程序或者命令 每一个进程都是运行的实体&#xff0c;都有自己的地址空间&#xff0c;并占有一定的资源空间 程序消耗的是磁盘资源、进程消耗的是内存和CPU资源 进程会占用四类资源&#xff08;CPU 、内存、磁盘、网…

会声会影电影片头怎么做 会声会影电影质感调色技巧 会声会影视频制作教程 会声会影下载免费中文版

片头通常通过一系列的图像、音乐和文字等元素来引入电影的主题和氛围。通过视觉和音频的呈现方式&#xff0c;给观众留下深刻的第一印象&#xff0c;为电影的故事铺设基础。这篇文章来学习一下会声会影电影片头怎么做&#xff0c;会声会影电影质感调色技巧。 一、会声会影电影…

力扣每日一题-拆炸弹-2024.5.5

力扣题目&#xff1a;拆炸弹 题目链接: 1652.拆炸弹 题目描述 代码思路 根据代码实现分为k等于0和k不等于0的情况。k等于0很容易处理&#xff0c;而k不等于0时&#xff0c;需要使用滑动窗口的方式来解决。先根据小于0或大于0确定一个窗口&#xff0c;然后移动&#xff0c;获…

【数据结构与算法】之五道链表进阶面试题详解!

目录 1、链表的回文结构 2、相交链表 3、随机链表的复制 4、环形链表 5、环形链表&#xff08;||&#xff09; 6、完结散花 个人主页&#xff1a;秋风起&#xff0c;再归来~ 数据结构与算法 个人格言&#xff1a;悟已往之不谏&#xff0c;知…

Llama3-Tutorial之Llama3本地Web Demo部署

Llama3-Tutorial之Llama3本地 Web Demo部署 Llama3-Tutorial之Llama3本地Web Demo部署章节。 参考&#xff1a; https://github.com/SmartFlowAI/Llama3-Tutorial 1. 环境配置 conda create -n llama3 python3.10conda activate llama3conda install pytorch2.1.2 torchvision0…

全球260多个国家的年通货膨胀率数据集(1960-2021年)

01、数据简介 全球年通货膨胀率是指全球范围内&#xff0c;在一年时间内&#xff0c;物价普遍上涨的比率。这种上涨可能是由于货币过度供应、需求过热、成本上升等原因导致的。通货膨胀率是衡量一个国家或地区经济状况和物价水平的重要指标&#xff0c;通常以消费者价格指数&a…

模板初阶篇

本篇目标 泛型编程函数模板类模板 一、泛型编程 下面是实现一个通用的交换函数 void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& left, double& right) {double temp left;left right;right temp; } v…

使用cloudflare实现访问LLM-API

一直在找调用第三方 LLM-API 的方法&#xff0c;看到有人用 cloudflare 实现&#xff0c;就尝试了一下&#xff0c;果然成功了。 突然发现&#xff0c;cloudflare 的功能真是个好东西&#xff0c;功能远超于本文所述。 1 相关网站 中文官网 - https://www.cloudflare-cn.com/注…

vue3—项目创建

背景 初次学习vue3&#xff0c;需要从项目创建开始。 步骤 打开cmd命令行&#xff0c;进入项目存放目录下&#xff0c;执行创建命令&#xff1a; npm create vuelatest 这一指令将会安装并执行 create-vue&#xff0c;它是 Vue 官方的项目脚手架工具。你将会看到一些诸如 …

通过Samba实现Windows和Linux之间进行共享文件

关于Samba 在嵌入式系统开发应用平台中&#xff0c;我们会常使用比如tftp、nfs和samba等服务器&#xff0c;来进行文件的传输&#xff0c;其中tftp和nfs是在嵌入式Linux开发环境中经常使用的传输工具&#xff0c;而samba则是Linux和Windows之间的文件传输工具。samba是模仿Wind…

第三篇、利用潜空间生成超稳定动画

1、使用temporal-kit&#xff0c;生成拼接的图片 sides填写3&#xff0c;Height Resolution要填写原视频高度 * sides ,这里也就是三倍 因为原视频动作很快&#xff0c;frames per keyframe填写了2 发现在temp1目录的Input目录下生成了 3* 3的拼接图片 2、到图生图界面&#…

【动态规划】路径问题

1.不同路径 不同路径 思路&#xff1a; 状态表示 状态转移方程 class Solution { public:int uniquePaths(int m, int n) {// 创建dp表// 初始化// 填表// 返回值vector<vector<int>> dp(m 1, vector<int>(n 1));dp[0][1] 1;for(int i 1; i < m; i…

认识ansible 了解常用模块

ansible是什么&#xff1f; Ansible是一个基于Python开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pubbet和Saltstack能实现的功能&#xff0c;Ansible基本上都可以实现。是自动化运维工具&#xff0…

好惨啊!科研路上的经验教训…

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

知识图谱基础

三元组的定义 定义&#xff1a;在知识图谱中&#xff0c;三元组是由三个元素组成的有序集合&#xff0c;分别是主体&#xff08;subject&#xff09;、谓词&#xff08;predicate&#xff09;和客体&#xff08;object&#xff09;。例如&#xff0c;“苹果是水果”的三元组可…

深入了解C/C++的内存区域划分

&#x1f525;个人主页&#xff1a;北辰水墨 &#x1f525;专栏&#xff1a;C学习仓 本节我们来讲解C/C的内存区域划分&#xff0c;文末会附加一道题目来检验成果&#xff08;有参考答案&#xff09; 一、大体有哪些区域&#xff1f;分别存放什么变量开辟的空间&#xff1f; …

ROS 2边学边练(43)-- 利用GTest写一个基本测试(C++)

前言 在ROS&#xff08;Robot Operating System&#xff09;中&#xff0c;gtest&#xff08;Google Test&#xff09;是一个广泛使用的C测试框架&#xff0c;用于编写和执行单元测试。这些测试可以验证ROS节点、服务和消息等的正确性和性能。 如果我们需要在写的包中添加测试&…

红黑树

一、红黑树用在哪里 HashMap。Linux 进程调度 CFS。Epoll 事件块的管理。Nginx Timer 事件管理。&#xff08;key&#xff0c;value&#xff09;的形式&#xff0c;并且中序遍历是顺序的&#xff0c;红黑树是二叉排序树。 二、红黑树性质 每个节点是红色或者黑色。根节点是黑…

Mybatis进阶3--注解开发

先看&#xff1a; Mybatis进阶1-CSDN博客 Mybatis进阶2-CSDN博客 mybatis注解开发 前置&#xff1a;不需要xxxMapper..xml文件&#xff08;映射文件&#xff09; 在核心配置文件中&#xff1a;<mappers>标签只能使用&#xff1a;<package name"扫描的包&quo…
最新文章