Springboot + redis分散式鎖

Hello霖發表於2024-03-31

1.引入redis和redisson

<!--        redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

<!--        redisson-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.16.4</version>
        </dependency>

2.配置一下

application.yml裡面加上 redisson配置檔案

redisson:
  config: classpath:redisson.yaml

新建一個redisson.yaml 填一些redis配置

singleServerConfig:
  # Redis 伺服器的地址
  address: "redis://127.0.0.1:6379"
  # 連線池的大小
  connectionPoolSize: 64
  # Redis 資料庫索引
  database: 0
  # 超時時間,單位為毫秒
  timeout: 3000
  # Redis 命令失敗重試次數
  retryAttempts: 3
  # 兩次命令之間重試的時間間隔,單位為毫秒
  retryInterval: 1500
  # 釋出和訂閱的連線的最小數量
  subscriptionConnectionMinimumIdleSize: 1
  # 釋出和訂閱的連線池的大小
  subscriptionConnectionPoolSize: 50
  # 當前處理 Redis 命令的執行緒共享的聯接
  connectionMinimumIdleSize: 10

redisson還要一個配置類:

@Configuration
public class RedissonConfig {

    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://localhost:6379");
        return Redisson.create(config);
    }
}

這樣配置完基本上ok了,然後就可以直接 lock , unlock 來進行獲取鎖和釋放鎖的操作。

3.實踐

下面這個場景是模擬 做一個使用者匹配的操作,例如相親配對使用者,某使用者很熱門,許多使用者爭搶匹配,但是該使用者只有一個,防止出現超匹配的問題,就要進行上鎖

//   注入Redisson
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public User matchId(Integer id) {
        RLock lock = redissonClient.getLock("lock_" + id);
        try {
            if (lock.tryLock()) {
                // 獲取鎖成功,執行業務邏輯
                User user = userMapper.selectById(id);
                if (user != null) {
                    // 執行匹配邏輯
                    // ...
                    System.out.println("匹配成功");
                    return user;
                } else {
                    System.out.println("使用者不匹配或已被匹配");
                }
            }
//            鎖被其他人佔用著
            else {
                System.out.println("匹配請求處理中,請稍後再試");
            }
        } catch (Exception e) {
            Thread.currentThread().interrupt();
            System.out.println("匹配請求被中斷");
        } finally {
            // 釋放鎖
            lock.unlock();
        }
        return null;
    }

上面的還是一個單節點redis的操作,如果要部署叢集redis的話,就可以用上 redlock的方法,

保證叢集的全部節點都來管理同一個鎖的狀態,防止某個上鎖的節點突然崩潰了,然後其它某個節點是沒上鎖的狀態,就可以進行多次匹配的問題

相關文章