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

Redisson 介绍

Redisson 介绍

Redisson 是一个高级的 Redis 客户端,基于 Netty 框架实现,提供了丰富的分布式对象和服务。它不仅简化了 Redis 的使用,还提供了分布式锁、集合、映射等高级功能。

Redisson 核心特性

1. 基础功能

  • 连接池管理:自动管理连接,支持哨兵、集群模式
  • 异步支持:提供同步、异步、响应式三种 API
  • 序列化:支持多种序列化方式(JSON、Kryo、FST 等)
  • 重连机制:自动重连和故障转移

2. 高级功能

  • 分布式锁:可重入锁、公平锁、读写锁、联锁、红锁
  • 分布式集合:Map、Set、List、Queue、Deque 等
  • 分布式对象:原子性 Long、BitSet、HyperLogLog 等
  • 分布式服务:远程服务、发布订阅、调度服务

Redisson 配置

Maven 依赖

<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.24.3</version> </dependency>

单机模式配置

Config config = new Config(); config.useSingleServer() .setAddress("redis://127.0.0.1:6379") .setPassword("yourpassword") .setDatabase(0) .setConnectionPoolSize(64) .setConnectionMinimumIdleSize(10); RedissonClient redisson = Redisson.create(config);

哨兵模式配置

Config config = new Config(); config.useSentinelServers() .addSentinelAddress("redis://sentinel1:26379", "redis://sentinel2:26379", "redis://sentinel3:26379") .setMasterName("mymaster") .setPassword("yourpassword"); RedissonClient redisson = Redisson.create(config);

集群模式配置

Config config = new Config(); config.useClusterServers() .addNodeAddress("redis://node1:6379", "redis://node2:6379", "redis://node3:6379") .setPassword("yourpassword") .setScanInterval(2000); RedissonClient redisson = Redisson.create(config);

Redisson 分布式锁详解

Redisson 实现了多种分布式锁,下面详细介绍每种锁的特性和使用方式。

1. 可重入锁(Reentrant Lock)

特性

  • 支持同一线程多次获取锁
  • 自动续期(看门狗机制)
  • 可设置锁超时时间
  • 阻塞式和非阻塞式获取

基本使用

// 获取锁对象 RLock lock = redisson.getLock("myLock"); // 阻塞式获取锁 lock.lock(); try { // 执行业务逻辑 System.out.println("执行业务代码"); } finally { // 释放锁 lock.unlock(); } // 尝试获取锁(非阻塞) if (lock.tryLock()) { try { // 执行业务逻辑 } finally { lock.unlock(); } } // 带超时的尝试获取 if (lock.tryLock(10, 30, TimeUnit.SECONDS)) { try { // 等待10秒获取锁,锁持有30秒 } finally { lock.unlock(); } }

看门狗机制

// 不指定超时时间,使用看门狗自动续期 lock.lock(); // 默认30秒自动续期 try { // 业务逻辑执行时间可以超过30秒 // 锁会自动续期,直到unlock() Thread.sleep(60000); } finally { lock.unlock(); }

自定义超时

// 指定超时时间,不使用看门狗 lock.lock(10, TimeUnit.SECONDS); try { // 10秒后锁自动释放,不会续期 } finally { lock.unlock(); }

2. 公平锁(Fair Lock)

特性

  • 按照请求顺序获取锁
  • 避免饥饿现象
  • 性能略低于可重入锁

使用方式

RLock fairLock = redisson.getFairLock("myFairLock"); // 阻塞式获取 fairLock.lock(); try { // 执行业务逻辑 } finally { fairLock.unlock(); } // 带超时的获取 if (fairLock.tryLock(10, 30, TimeUnit.SECONDS)) { try { // 执行业务逻辑 } finally { fairLock.unlock(); } }

3. 读写锁(ReadWrite Lock)

特性

  • 读锁(共享锁):多个线程可以同时持有
  • 写锁(排他锁):独占访问
  • 读读不互斥,读写互斥,写写互斥

使用方式

RReadWriteLock rwLock = redisson.getReadWriteLock("myRWLock"); // 读锁 RLock readLock = rwLock.readLock(); readLock.lock(); try { // 多个线程可以同时读取 String data = "读取数据"; System.out.println(data); } finally { readLock.unlock(); } // 写锁 RLock writeLock = rwLock.writeLock(); writeLock.lock(); try { // 独占写入 System.out.println("写入数据"); } finally { writeLock.unlock(); }

实际应用场景

// 缓存读写场景 public class CacheService { private RReadWriteLock rwLock; public CacheService(RedissonClient redisson) { this.rwLock = redisson.getReadWriteLock("cache:rwlock"); } public String getData(String key) { RLock readLock = rwLock.readLock(); readLock.lock(); try { // 读数据 return redisson.getBucket(key).get(); } finally { readLock.unlock(); } } public void setData(String key, String value) { RLock writeLock = rwLock.writeLock(); writeLock.lock(); try { // 写数据 redisson.getBucket(key).set(value); } finally { writeLock.unlock(); } } }

4. 联锁(MultiLock)

特性

  • 同时锁定多个对象
  • 所有锁都获取成功才算成功
  • 用于跨资源的一致性操作

使用方式

RLock lock1 = redisson1.getLock("lock1"); RLock lock2 = redisson2.getLock("lock2"); RLock lock3 = redisson3.getLock("lock3"); // 创建联锁 RLock multiLock = redisson.getMultiLock(lock1, lock2, lock3); try { // 同时获取多个锁 multiLock.lock(); // 执行跨资源的业务逻辑 } finally { multiLock.unlock(); }

5. 红锁(RedLock)

特性

  • 分布式高可用锁
  • 需要在多个 Redis 实例上加锁
  • 大多数节点成功才算成功
  • 防止单点故障

使用方式

// 配置多个Redis实例 Config config1 = new Config(); config1.useSingleServer().setAddress("redis://node1:6379"); RedissonClient redisson1 = Redisson.create(config1); Config config2 = new Config(); config2.useSingleServer().setAddress("redis://node2:6379"); RedissonClient redisson2 = Redisson.create(config2); Config config3 = new Config(); config3.useSingleServer().setAddress("redis://node3:6379"); RedissonClient redisson3 = Redisson.create(config3); // 获取红锁 RLock lock1 = redisson1.getLock("myRedLock"); RLock lock2 = redisson2.getLock("myRedLock"); RLock lock3 = redisson3.getLock("myRedLock"); RLock redLock = redisson1.getRedLock(lock1, lock2, lock3); try { // 大多数节点成功才获取锁 redLock.lock(); // 执行业务逻辑 } finally { redLock.unlock(); }

6. 信号量(Semaphore)

特性

  • 限制同时访问的线程数
  • 基于计数器实现
  • 支持公平和非公平模式

使用方式

RSemaphore semaphore = redisson.getSemaphore("mySemaphore"); // 设置许可数 semaphore.trySetPermits(3); try { // 获取许可 semaphore.acquire(); // 执行业务逻辑(最多3个线程同时执行) } finally { // 释放许可 semaphore.release(); } // 非阻塞获取 if (semaphore.tryAcquire()) { try { // 执行业务逻辑 } finally { semaphore.release(); } }

7. 闭锁(CountDownLatch)

特性

  • 等待多个线程完成
  • 基于计数器实现
  • 一次性使用

使用方式

RCountDownLatch latch = redisson.getCountDownLatch("myLatch"); // 设置等待数量 latch.trySetCount(5); // 等待线程 new Thread(() -> { try { latch.await(); System.out.println("所有线程执行完毕"); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); // 工作线程 for (int i = 0; i < 5; i++) { new Thread(() -> { // 执行业务逻辑 System.out.println("工作线程执行"); // 计数减1 latch.countDown(); }).start(); }

Redisson 锁的最佳实践

1. 工具类封装

@Component public class DistributedLockUtil { @Autowired private RedissonClient redissonClient; /** * 执行带锁的业务逻辑 */ public <T> T executeWithLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit, Supplier<T> supplier) { RLock lock = redissonClient.getLock(lockKey); try { if (lock.tryLock(waitTime, leaseTime, unit)) { try { return supplier.get(); } finally { lock.unlock(); } } else { throw new RuntimeException("获取锁失败"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("锁等待被中断", e); } } /** * 无返回值的执行 */ public void executeWithLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit, Runnable runnable) { executeWithLock(lockKey, waitTime, leaseTime, unit, () -> { runnable.run(); return null; }); } }

2. 使用示例

@Service public class OrderService { @Autowired private DistributedLockUtil lockUtil; public void createOrder(String orderId) { lockUtil.executeWithLock( "order:lock:" + orderId, 10, // 等待10秒 30, // 锁持有30秒 TimeUnit.SECONDS, () -> { // 创建订单逻辑 System.out.println("创建订单: " + orderId); // 扣减库存 // 扣减余额 } ); } }

3. 注解方式实现

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface DistributedLock { String key(); long waitTime() default 10; long leaseTime() default 30; TimeUnit timeUnit() default TimeUnit.SECONDS; } @Aspect @Component public class DistributedLockAspect { @Autowired private RedissonClient redissonClient; @Around("@annotation(distributedLock)") public Object around(ProceedingJoinPoint point, DistributedLock distributedLock) throws Throwable { String lockKey = distributedLock.key(); RLock lock = redissonClient.getLock(lockKey); try { if (lock.tryLock(distributedLock.waitTime(), distributedLock.leaseTime(), distributedLock.timeUnit())) { try { return point.proceed(); } finally { lock.unlock(); } } else { throw new RuntimeException("获取锁失败"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("锁等待被中断", e); } } } // 使用 @Service public class InventoryService { @DistributedLock(key = "inventory:lock:#{#productId}") public void deductInventory(String productId, int quantity) { // 扣减库存逻辑 } }

Redisson 锁的底层原理

1. 锁获取过程

1. 客户端发送 Lua 脚本到 Redis 2. Redis 原子执行:SET key value NX PX timeout 3. 如果成功,启动看门狗线程 4. 如果失败,返回获取失败

2. 看门狗续期机制

1. 默认续期时间:30秒 2. 续期线程:每 10 秒检查一次 3. 如果锁还持有,续期 30 秒 4. 直到调用 unlock() 停止续期

3. 锁释放过程

1. 客户端发送 Lua 脚本 2. 检查锁是否属于当前线程 3. 如果属于,删除 key 4. 如果不属于,返回释放失败

注意事项

  1. 锁名称设计:要保证唯一性和可读性
  2. 超时时间:根据业务执行时间合理设置
  3. 异常处理:确保锁能正确释放
  4. 避免死锁:设置合理的超时时间
  5. 性能考虑:锁粒度不宜过大
http://www.jsqmd.com/news/699834/

相关文章:

  • 朴素分类器概率评估与优化实战
  • D6.3 PriorityClass 常用实验(2个)
  • DeepSeek创始人专访:中国的AI不可能永远跟随,需要有人站到技术的前沿
  • AutoCAD字体缺失终结者:FontCenter插件完整使用指南
  • Apache Doris 4.1:面向 AI Search 的统一数据存储与检索底座
  • DeepBump:从单张图片智能生成法线贴图的终极指南
  • 基于LLM嵌入的语义搜索引擎构建与实践
  • C++编写超低延迟MCP网关的成本控制实战(腾讯/蚂蚁级网关架构师内部分享·仅限首批200位开发者)
  • 工业Modbus调试神器:5分钟掌握OpenModScan,告别通讯故障烦恼
  • 打破传统娱乐局限,超元力无限方舟重塑沉浸体验新范式
  • 2026深度分析罗兰艺境化工材料GEO技术案例,测评景县密封件制造企业景顺密封优化过程与效果验证 - 罗兰艺境GEO
  • 算法训练营第十二天| 多数元素
  • 【行业首曝】VSCode 2026内嵌Vector CANoe Bridge插件深度评测:实现“编辑→编译→CAN帧注入→ECU响应追踪”全链路毫秒级闭环,效率提升217%?
  • Windows Cleaner终极指南:如何快速解决C盘爆红难题,释放20GB+空间
  • Java CompletableFuture 链式任务实践
  • CUDA 13内存模型变更引发的AI训练死锁频发?——基于Nsight Compute 2024.1.1的17个真实trace分析(含修复补丁)
  • 终极指南:3步掌握XELFViewer - 全平台ELF文件分析与编辑神器
  • MySQL LPAD()函数详解
  • 侠客工坊如何将普通手机如何变成AI手机,进化为24小时在线的AI数字员工?
  • 从UPF1.0到UPF2.1:Power Intent编写中那些容易踩的‘坑’与升级指南
  • Day3 C基础
  • 别再只盯着SQL注入了!从“任意账号注册”漏洞,聊聊开发中容易被忽视的业务逻辑安全
  • 国产化替代倒计时90天!VSCode 2026与IDEA/Rider在飞腾2000+/申威SW64平台的启动耗时、内存驻留、插件加载成功率三维对比(附原始perf数据包)
  • 多智能体协同中的竞态问题与分布式锁优化实践
  • 【PaddleOCR实战指南:图像文字识别、实时摄像头与PyQt5 GUI开发】
  • 两层板与四层板核心区别
  • Redis缓存实战:从数据类型到分布式锁,看完这篇就够了
  • 封神!C++ 对象时序管理终极解法——我发明的「构造回环策略」
  • 告别PPT内耗,从容上岸:百考通AI如何拯救你的毕业答辩
  • 宇宙学研究新突破:用 Blender 几何节点处理 CMB 数据,实现多项实用功能!