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

SpringBoot集成redisson自带分布式锁-快速集成亲测可用

前言

记录项目集成redisson

项目环境

springboot 2.7.5

jdk17

操作

pom.xml

<!-- Redisson --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <scope>compile</scope> <version>3.11.1</version> </dependency>

yml配置

spring: redis: host: 127.0.0.1 # Redis服务器地址 database: 4 # Redis数据库索引(默认为0) port: 6379 # Redis服务器连接端口 password: # Redis服务器连接密码(默认为空) timeout: 5000 # 连接超时时间(毫秒) lettuce: # 连接池最大阻塞等待时间(毫秒) shutdown-timeout: 10000 pool: # 连接池中的最小空闲连接 min-idle: 50 # 连接池中的最大空闲连接 max-idle: 100 # 连接池的最大数据库连接数 max-active: 3000 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: 300000
RedissonConfig
import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.codec.JsonJacksonCodec; import org.redisson.config.Config; import org.redisson.config.TransportMode; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Redisson配置类 * * @author Xx * @since 2024/10/28 11:12 */ @Configuration public class RedissonConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private String port; @Value("${spring.redis.password}") private String password; /** 默认使用0号数据库 */ @Value("${spring.redis.database:0}") private int database; @Bean public RedissonClient redisson() { Config config = new Config(); // 配置线程池 // 线程池数量,0=默认值: 当前处理核数量 * 2 config.setThreads(0) // Netty线程池数量,0=默认值: 当前处理核数量 * 2 .setNettyThreads(0) // 设置对象编码器,默认使用JsonJacksonCodec .setCodec(new JsonJacksonCodec()) // 传输模式,默认NIO .setTransportMode(TransportMode.NIO); // 单节点配置 config.useSingleServer() // 节点地址 .setAddress("redis://" + host + ":" + port) // Redis认证密码 .setPassword(password) // 客户端名称 .setClientName("making_friends") // 数据库编号 .setDatabase(database) // ==== 连接配置 ==== // 连接空闲超时时间,单位:毫秒 .setIdleConnectionTimeout(10000) // 连接超时时间,单位:毫秒 .setConnectTimeout(10000) // 命令等待超时时间,单位:毫秒 .setTimeout(3000) // 命令失败重试次数 // 如果尝试达到 retryAttempts 仍然不能将命令发送至某个指定的节点时,将抛出错误 // 如果尝试在此限制之内发送成功,则开始启用 timeout 计时 .setRetryAttempts(3) // 命令重试发送时间间隔,单位:毫秒 .setRetryInterval(1500) // ==== 订阅配置 ==== // 单个连接最大订阅数量 .setSubscriptionsPerConnection(10) // 发布和订阅连接的最小空闲连接数 .setSubscriptionConnectionMinimumIdleSize(5) // 发布和订阅连接池大小 .setSubscriptionConnectionPoolSize(50) // ==== 连接池配置 ==== // 最小空闲连接数 .setConnectionMinimumIdleSize(32) // 连接池大小 .setConnectionPoolSize(64) // ==== DNS监控 ==== // DNS变化扫描间隔,单位:毫秒 .setDnsMonitoringInterval(5000); // 创建并返回RedissonClient实例 return Redisson.create(config); } }
RedissonUtils
import java.util.Collection; import java.util.concurrent.TimeUnit; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RBatch; import org.redisson.api.RBloomFilter; import org.redisson.api.RBucket; import org.redisson.api.RList; import org.redisson.api.RLock; import org.redisson.api.RMap; import org.redisson.api.RRateLimiter; import org.redisson.api.RReadWriteLock; import org.redisson.api.RScoredSortedSet; import org.redisson.api.RSemaphore; import org.redisson.api.RSet; import org.redisson.api.RateIntervalUnit; import org.redisson.api.RateType; import org.redisson.api.RedissonClient; import org.springframework.stereotype.Component; /** * Redisson 工具类 * com.macro.mall.common.util.RedissonUtils * @author Xx * dateTime 2024/10/28 11:20 */ @Slf4j @Component public class RedissonUtils { @Resource private RedissonClient redissonClient; // ================ 通用操作 ================ /** * 删除key */ public void del(String key) { redissonClient.getBucket(key).delete(); } /** * 删除key */ public void delete(String key) { redissonClient.getBucket(key).delete(); } /** * 批量删除key */ public void delete(Collection<String> keys) { RBatch batch = redissonClient.createBatch(); keys.forEach(key -> batch.getBucket(key).deleteAsync()); batch.execute(); } /** * 检查key是否存在 */ public boolean hasKey(String key) { return redissonClient.getBucket(key).isExists(); } /** * 设置过期时间 */ public boolean expire(String key, long timeout, TimeUnit unit) { return redissonClient.getBucket(key).expire(timeout, unit); } /** * 获取过期时间 */ public long getExpire(String key, TimeUnit unit) { return redissonClient.getBucket(key).remainTimeToLive(); } // ================ 对象操作 ================ /** * 设置对象 */ public <T> void set(String key, T value) { RBucket<T> bucket = redissonClient.getBucket(key); bucket.set(value); } /** * 设置对象带过期时间 */ public <T> void set(String key, T value, long timeout, TimeUnit unit) { RBucket<T> bucket = redissonClient.getBucket(key); bucket.set(value, timeout, unit); } /** * 获取对象 */ public <T> T get(String key) { RBucket<T> bucket = redissonClient.getBucket(key); return bucket.get(); } // ================ 原子操作 ================ /** * 原子递增 */ public long incr(String key, long delta) { return redissonClient.getAtomicLong(key).addAndGet(delta); } /** * 原子递减 */ public long decr(String key, long delta) { return redissonClient.getAtomicLong(key).addAndGet(-delta); } // ================ 分布式锁 ================ /** * 获取可重入锁 */ public RLock getLock(String key) { return redissonClient.getLock(key); } /** * 获取公平锁 */ public RLock getFairLock(String key) { return redissonClient.getFairLock(key); } /** * 获取读写锁 */ public RReadWriteLock getReadWriteLock(String key) { return redissonClient.getReadWriteLock(key); } /** * 获取信号量 */ public RSemaphore getSemaphore(String key) { return redissonClient.getSemaphore(key); } // ================ 集合操作 ================ /** * 获取列表 */ public <T> RList<T> getList(String key) { return redissonClient.getList(key); } /** * 获取集合 */ public <T> RSet<T> getSet(String key) { return redissonClient.getSet(key); } /** * 获取有序集合 */ public <T> RScoredSortedSet<T> getSortedSet(String key) { return redissonClient.getScoredSortedSet(key); } /** * 获取映射 */ public <K, V> RMap<K, V> getMap(String key) { return redissonClient.getMap(key); } // ================ 限流器 ================ /** * 获取限流器 */ public RRateLimiter getRateLimiter(String key) { return redissonClient.getRateLimiter(key); } /** * 创建限流器 * * @param key 限流器key * @param rate 每秒允许的请求数 * @param rateInterval 时间间隔,默认1秒 */ public RRateLimiter createRateLimiter(String key, long rate, long rateInterval) { RRateLimiter rateLimiter = redissonClient.getRateLimiter(key); rateLimiter.trySetRate(RateType.OVERALL, rate, rateInterval, RateIntervalUnit.SECONDS); return rateLimiter; } // ================ 布隆过滤器 ================ /** * 获取布隆过滤器 */ public <T> RBloomFilter<T> getBloomFilter(String key) { return redissonClient.getBloomFilter(key); } /** * 创建布隆过滤器 * * @param key 布隆过滤器key * @param expectedInsertions 预期插入数量 * @param falseProbability 误判率 */ public <T> RBloomFilter<T> createBloomFilter(String key, long expectedInsertions, double falseProbability) { RBloomFilter<T> bloomFilter = redissonClient.getBloomFilter(key); bloomFilter.tryInit(expectedInsertions, falseProbability); return bloomFilter; } // ================ 使用示例 ================ /** * 分布式锁示例 */ public void lockExample() { RLock lock = getLock("myLock"); try { // 尝试加锁,最多等待100秒,上锁10秒后自动解锁 if (lock.tryLock(100, 10, TimeUnit.SECONDS)) { try { // 业务逻辑 } finally { lock.unlock(); } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); log.error("获取锁异常", e); } } /** * 限流器示例 */ public boolean rateLimitExample() { RRateLimiter rateLimiter = createRateLimiter("myRateLimiter", 10, 1); // 尝试获取一个令牌 return rateLimiter.tryAcquire(1); } /** * 布隆过滤器示例 */ public void bloomFilterExample() { RBloomFilter<String> bloomFilter = createBloomFilter("myBloomFilter", 10000, 0.01); // 添加元素 bloomFilter.add("item1"); // 判断元素是否存在 boolean exists = bloomFilter.contains("item1"); } }

分布式锁测试

@Autowired private RedissonUtils redissonUtils; @SneakyThrows @Test void ts() { // 获取分布式锁 RLock lock = redissonUtils.getLock("myLock"); // 尝试在 30 秒内获取锁,如果超时则返回 false if (lock.tryLock(300, 300, java.util.concurrent.TimeUnit.SECONDS)) { try { // 执行任务 System.out.println("Executing critical section with distributed lock..."); } finally { lock.unlock(); // 释放锁 } } else { System.out.println("Failed to acquire lock."); } }
http://www.jsqmd.com/news/618985/

相关文章:

  • 如何构建高性能帧同步游戏:ET框架预测回滚技术深度解析
  • JMS, ActiveMQ 学习一则纲
  • muffet源码解析:深入理解HTTP客户端池与并发控制机制
  • 在 Kubernetes 上部署 Ollama3
  • 【芯片可靠性实战】Bhast测试:从标准解读到硬件执行的完整指南
  • VoxelMorph核心模型解析:从VxmPairwise到SynthMorph的完整架构
  • Zip框架核心原理解析:从minizip到Swift封装的技术内幕
  • 如何在5分钟内开始使用EmulatorJS:新手完整入门教程
  • 别再下错包了!手把手教你获取ROS2 Humble可用的gazebo_grasp_plugin正确分支
  • 论文阅读:arxiv 2026 A Systematic Security Evaluation of OpenClaw and Its Variants
  • FreeRTOS(实时操作系统)
  • React Native Safe Area Context 终极指南:Android、iOS、Web 跨平台适配解决方案
  • 【AI原生系统容灾黄金标准】:20年架构师亲授3层冗余+5分钟RTO实战设计法
  • 【独家首发】2026奇点大会闭门报告流出:全球TOP20 AI原生开源项目活跃度、许可证风险与国产替代窗口期(仅限72小时可查)
  • 革命性AI搜索平台Trieve:一站式解决语义搜索与RAG所有难题
  • 手把手教你用Multisim和Matlab复现《开关电源控制环路设计》第一章的所有仿真案例
  • 终极指南:如何用VideoSrt为视频快速生成专业字幕
  • Ion.RangeSlider跨浏览器兼容性深度解析与优化方案
  • 安全信息和事件管理(SIEM):定义、工作原理、核心功能与应用场景
  • 大模型应用开发面试题(来自牛客网)
  • QmlBook深度解析:Qt5与QML的核心概念与架构设计
  • 【GUI-Agent】阶跃星辰 GUI-MCP 解读---()---命令解析和工具映射聪
  • MIST:如何用开源工具解决显微图像拼接的常见困扰?
  • Qwen-Image-Edit-F2P与计算机网络:分布式推理系统设计
  • 使用小龙虾来操作猿编程的遥控车顺
  • STC8H单片机学习-GPIO的四种模式
  • 如何高效使用awesome-italia-remote进行职业规划:5步策略指南
  • STM32 MODBUS-RTU通讯调试避坑指南:从串口助手数据帧分析到CRC校验失败排查
  • JW Player播放列表管理完全手册:实现智能视频序列播放
  • RAG 索引优化:让检索又准又快的两把钥匙