Redis分布式锁Redisson

灰太狼 2023-10-07 19:31 161阅读 0赞

文章目录

  • 分布式锁
    • 不可重入Redis分布式锁
  • Redisson
    • 快速入门
      • 可重入的Redis分布式锁
      • Redisson的multiLock

分布式锁

分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。

分布式锁的核心是实现多进程之间互斥,而满足这一点的方式有很多,常见的有三种:

在这里插入图片描述

不可重入Redis分布式锁

原理:利用setnx的互斥性;利用ex避免死锁;释放锁时判断线程标示 缺陷:不可重入、无法重试、锁超时失效

实现分布式锁时需要实现的两个基本方法:

  • 获取锁:

    • 互斥:确保只能有一个线程获取锁

      • 添加锁,利用setnx的互斥特性
      • 添加锁过期时间,避免服务宕机引起的死锁

在这里插入图片描述

  • 释放锁

    • 手动释放
    • 超时释放:获取锁时添加一个超时时间

    释放锁,删除即可

    DEL key

分布式锁实现,满足:

在获取锁时存入线程标示(可以用UUID表示)
在释放锁时先获取锁中的线程标示,判断是否与当前线程标示一致
如果一致则释放锁
如果不一致则不释放锁

Redisson

https://github.com/redisson/redisson

快速入门

可重入的Redis分布式锁

原理:利用hash结构,记录线程标示和重入次数;利用watchDog延续锁时间;利用信号量控制锁重试等待
缺陷:redis宕机引起锁失效问题

依赖

  1. <dependency>
  2. <groupId>org.redisson</groupId>
  3. <artifactId>redisson</artifactId>
  4. <version>3.13.6</version>
  5. </dependency>

配置Redisson客户端:

  1. import org.redisson.Redisson;
  2. import org.redisson.api.RedissonClient;
  3. import org.redisson.config.Config;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. @Configuration
  7. public class RedisConfig {
  8. @Bean
  9. public RedissonClient redisClient() {
  10. Config config = new Config();
  11. config.useSingleServer().setAddress("redis://47.96.16.107:6379").setPassword("654321");
  12. return Redisson.create(config);
  13. }
  14. }

使用

  1. @Resource
  2. private RedissonClient redissonClient;
  3. @Test
  4. void testRedisson() throws InterruptedException {
  5. // 获取锁(可重入),指定锁的名称
  6. RLock lock = redissonClient.getLock("anyLock");
  7. // 尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位
  8. boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);
  9. // 判断释放获取成功
  10. if (isLock) {
  11. try {
  12. System.out.println("执行业务");
  13. } finally {
  14. // 释放锁
  15. lock.unlock();
  16. }
  17. }
  18. }

Redisson的multiLock

配置类

  1. import org.redisson.Redisson;
  2. import org.redisson.api.RedissonClient;
  3. import org.redisson.config.Config;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. @Configuration
  7. public class RedisConfig {
  8. @Bean
  9. public RedissonClient redisClient1() {
  10. Config config = new Config();
  11. config.useSingleServer().setAddress("redis://47.96.16.107:6379").setPassword("654321");
  12. return Redisson.create(config);
  13. }
  14. @Bean
  15. public RedissonClient redisClient2() {
  16. Config config = new Config();
  17. config.useSingleServer().setAddress("redis://47.96.16.107:6380").setPassword("654321");
  18. return Redisson.create(config);
  19. }
  20. @Bean
  21. public RedissonClient redisClient3() {
  22. Config config = new Config();
  23. config.useSingleServer().setAddress("redis://47.96.16.107:6381").setPassword("654321");
  24. return Redisson.create(config);
  25. }
  26. }

multiLock

  1. import lombok.extern.slf4j.Slf4j;
  2. import org.junit.jupiter.api.Test;
  3. import org.redisson.api.RLock;
  4. import org.redisson.api.RedissonClient;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import javax.annotation.Resource;
  8. import java.util.concurrent.TimeUnit;
  9. @Slf4j
  10. @SpringBootTest
  11. class SimpleLockTest {
  12. @Resource
  13. private RedissonClient redissonClient1;
  14. @Resource
  15. private RedissonClient redissonClient2;
  16. @Resource
  17. private RedissonClient redissonClient3;
  18. @Test
  19. void testRedisson() throws InterruptedException {
  20. RLock lock1 = redissonClient1.getLock("apple");
  21. RLock lock2 = redissonClient2.getLock("apple");
  22. RLock lock3 = redissonClient3.getLock("apple");
  23. RLock lock = redissonClient1.getMultiLock(lock1, lock2, lock3);
  24. // // 获取锁(可重入),指定锁的名称
  25. // RLock lock = redissonClient.getLock("anyLock");
  26. // 尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位
  27. boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);
  28. // 判断释放获取成功
  29. if (isLock) {
  30. try {
  31. System.out.println("执行业务");
  32. } finally {
  33. // 释放锁
  34. lock.unlock();
  35. }
  36. }
  37. }

发表评论

表情:
评论列表 (有 0 条评论,161人围观)

还没有评论,来说两句吧...

相关阅读