当前位置: 首页 > news >正文

Java集成Redisson实现分布式锁(实战)

一、Redisson是什么

Redisson 是一个基于 Redis 实现的 Java 驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列分布式和可扩展的 Java 数据结构,还对 Redis 进行了封装,让开发者可以更便捷地使用 Redis。

二、Redisson作用

  1. 简化 Redis 操作:Redisson 为 Java 开发者提供了一套直观且易于使用的 API,能把 Redis 当作普通的 Java对象或集合来操作,从而减少了与 Redis 交互时的复杂度。例如,你可以像操作 Java 的Map一样操作 Redis 中的哈希表。
  2. 分布式锁和同步机制:Redisson实现了多种分布式锁和同步工具,如可重入锁、公平锁、读写锁等,能确保在分布式环境下多个节点之间的数据一致性和并发控制。
  3. 丰富的数据结构:它提供了分布式的Map、List、Set、Queue等数据结构,这些结构在分布式系统中能被多个节点共享和操作。
  4. 异步和反应式编程支持:Redisson 支持异步和反应式编程模型,可提升应用程序的性能和响应能力。

三、使用场景

  1. 分布式锁:在分布式系统中,多个服务可能会同时访问和修改共享资源,使用 Redisson 的分布式锁可以保证同一时间只有一个服务能够操作该资源,避免数据冲突。例如,在电商系统中,多个订单服务可能同时处理库存扣减的操作,使用分布式锁可以确保库存数据的准确性。
  2. 分布式集合:当需要在多个服务之间共享数据时,可以使用 Redisson的分布式集合。比如,在一个分布式的消息系统中,多个消费者服务可以通过分布式队列来处理消息。
  3. 分布式缓存:利用 Redisson 的分布式Map可以实现分布式缓存,将经常访问的数据存储在 Redis 中,减少数据库的访问压力,提高系统的性能。例如,在一个高并发的 Web 应用中,可以将用户的基本信息缓存在 Redis 中,当用户访问时直接从缓存中获取数据。
  4. 分布式信号量:在分布式系统中,信号量可用于控制对有限资源的访问。例如,在一个分布式的文件上传系统中,可以使用信号量来限制同时上传的文件数量。

四、使用

1、引入依赖:

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>${redisson.version}</version>  <!--版本号根据项目适配-->
</dependency>

3、配置文件

# 数据源配置
spring:# redis 配置redis:# 地址host: 127.0.0.1# 端口,默认为6379port: 6379# 数据库索引database: 5# 密码password: # 连接超时时间timeout: 60slettuce:pool:# 连接池中的最小空闲连接min-idle: 0# 连接池中的最大空闲连接max-idle: 8# 连接池的最大数据库连接数max-active: 8# #连接池最大阻塞等待时间(使用负值表示没有限制)max-wait: -1ms

3、配置类:

@Component
@RefreshScope
public class RedissonConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private String port;@Value("${spring.redis.password}")private String password;@Value("${spring.redis.database}")private Integer database;@Beanpublic RedissonClient redissonClient() {// 创建配置 指定redis地址及节点信息Config config = new Config();//单例模式config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password) // redis设置了密码,就需设置.setDatabase(database);// 根据config创建出RedissonClient实例并返回return Redisson.create(config);}
}

4、工具

@Slf4j
@Component
public class RedissonLock {@Resourceprivate RedissonClient redissonClient;/*** lock(), 拿不到lock就不罢休,不然线程就一直block*/public RLock lock(String key) {if (StringUtils.isBlank(key)) {return null;}RLock lock = redissonClient.getLock(key);try {lock = redissonClient.getLock(key);} catch (Exception e) {log.error("Failed to acquire lock for key: " + key, e);}return lock;}/*** leaseTime为加锁时间,单位为秒* @param key key* @param leaseTime 为加锁时间,单位为秒*/public RLock lock(String key, long leaseTime) {if (StringUtils.isBlank(key) || leaseTime <= 0) {return null;}RLock lock = redissonClient.getLock(key);try {lock.lock(leaseTime, TimeUnit.SECONDS);} catch (Exception e) {log.error("Failed to acquire lock for key: " + key, e);}return lock;}/*** timeout为加锁时间,时间单位由unit确定*/public RLock lock(String key, TimeUnit unit, long timeout) {if (StringUtils.isBlank(key) || timeout <= 0 || unit == null) {return null;}RLock lock = redissonClient.getLock(key);try {lock.lock(timeout, unit);} catch (Exception e) {log.error("Failed to acquire lock for key: " + key, e);}return lock;}/*** @param lockKey   锁 key* @param unit      单位* @param waitTime  等待时间* @param leaseTime 锁有效时间* @return 加锁成功? true:成功 false: 失败*/public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {RLock lock = redissonClient.getLock(lockKey);try {return lock.tryLock(waitTime, leaseTime, unit);} catch (InterruptedException e) {Thread.currentThread().interrupt();log.error("加锁失败: " + e.getMessage());return false;} catch (Exception e) {log.error("加锁过程中发生异常: " + e.getMessage());return false;}}/*** unlock** @param lockKey key*/public void unlock(String lockKey) {RLock lock = redissonClient.getLock(lockKey);if (lock.isLocked() && lock.isHeldByCurrentThread()) {lock.unlock();}}/*** unlock** @param lock 锁*/public void unlock(RLock lock) {lock.unlock();}
}

5、例子

@RestController
@Slf4j
public class RedissonController {@Resourceprivate RedissonLock redissonLock;@GetMapping("lockTest")public void lockTest(String key) {// 获取锁RLock lock = redissonLock.getLock(key);try {// 加锁lock.lock();System.out.println("获取到锁,开始执行任务");// 模拟业务操作Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();} finally {// 释放锁lock.unlock();System.out.println("任务执行完毕,释放锁");}
}

总结

Lock和tryLock的区别
在这里插入图片描述

相关文章:

  • 热带气旋【CH报文数据插值】中央气象台-台风路径数据每小时插值
  • 【EDA】Multi-Net Routing(多网布线)
  • 【计算机视觉】CV实战项目 - 深入解析基于HOG+SVM的行人检测系统:Pedestrian Detection
  • 写在后面的话
  • 11.AOP开发
  • BS客户端的单点登录
  • 东南亚与中东小游戏市场出海调研报告
  • 7.0 sharpScada的sql数据的安装
  • 如何解决windows端口被占用
  • Kubernetes 节点 Not Ready 时 Pod 驱逐机制深度解析(下)
  • Java—— 常见API介绍 第四期
  • 【多目标进化算法】常见多目标进化算法一览
  • IP查询专业版:支持IPv4/IPv6自动识别并切换解析的API接口使用指南
  • C++ (STL,顺序容器,关联容器,容器适配器)
  • markdown自动标题序号,标题序号,目录处理
  • 软件设计模式与体系结构:基于Java实现管道-过滤器架构
  • RunnerGo API性能测试实战与高并发调优
  • SQL Server 2019 安装与配置详细教程
  • 区间和数量统计 之 前缀和+哈希表
  • Linux内核参数调优(TCP BBR算法实践)
  • 新城市志|中国消费第一城,迎来“补贴力度最大”购物节
  • 陈平评《艺术科学的目的与界限》|现代艺术史学的奠基时代
  • 新希望去年归母净利润4.74亿同比增逾九成,营收降27%
  • 江苏、安徽跨省联动共治“样板间”:进一扇门可办两省事
  • 贵州通报9起群众身边不正之风和腐败问题典型案例
  • 调查丨当节气出现“时差”,陕西的果农们经历着什么?