重学SpringBoot3-集成Redis(四)之Redisson

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》

期待您的点赞👍收藏⭐评论✍

重学SpringBoot3-集成Redis(四)之Redisson

  • [1. 添加 Redisson 依赖](#1. 添加 Redisson 依赖)
  • [2. 配置 Redisson 客户端](#2. 配置 Redisson 客户端)
  • [3. 使用 Redisson 实现分布式锁](#3. 使用 Redisson 实现分布式锁)
  • [4. 调用分布式锁](#4. 调用分布式锁)
  • [5. 为什么使用Redisson分布式锁](#5. 为什么使用Redisson分布式锁)
  • [6. 常见问题](#6. 常见问题)
  • [7. 总结](#7. 总结)

在 Spring Boot 3 中,整合 Redisson 实现分布式锁可以有效地解决分布式环境下的并发问题。Redisson 是 Redis 官方推荐的客户端,它提供了丰富的分布式对象和高级功能,包括分布式锁的实现。下面介绍如何使用 Spring Boot 3 和 Redisson 来实现分布式锁的功能。

1. 添加 Redisson 依赖

首先,需要在 pom.xml 中添加 Redisson 的依赖,并确保已经引入了 Spring Boot 和 Redis 的相关依赖:

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.23.4</version>
        </dependency>

2. 配置 Redisson 客户端

在 application.yml 文件中,配置 Redis 的连接信息,此例以单机版 Redis 为例。config: 后面跟着一个管道符 (|),表示一个多行字符串,也就是一个整体。

yaml 复制代码
spring:
  redis:
    redisson:
      config: |
        singleServerConfig:
          address: redis://localhost:6379    # Redis 连接地址,前缀为 redis://
          password: 			             # 如果 Redis 需要密码认证,则填写密码
          timeout: 3000                      # 命令执行超时时间(毫秒)

如果使用的是 Redis 集群则需要修改为如下配置:

yaml 复制代码
spring:
  redis:
    redisson: 
      config: |
        clusterServersConfig:
          password: 
          nodeAddresses:
          - redis://127.0.0.1:6379
          - redis://127.0.0.2:6379
          - redis://127.0.0.3:6379

接着,在配置类中初始化 Redisson 客户端。

java 复制代码
package com.coderjia.boot310redis.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.spring.starter.RedissonProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author CoderJia
 * @create 2024/10/5 下午 04:53
 * @Description
 **/
@Configuration
public class RedissonConfig {

    @Autowired
    private RedissonProperties redissonProperties;

    @Bean
    public RedissonClient redissonClient() throws Exception{
        Config config = Config.fromYAML(redissonProperties.getConfig());
        Redisson.create(config);
        System.out.println("Redisson 已启动");
        return Redisson.create(config);
    }

}

3. 使用 Redisson 实现分布式锁

通过 RedissonClient,我们可以使用分布式锁功能。下面是一个简单的示例,展示如何使用 Redisson 实现分布式锁。

java 复制代码
package com.coderjia.boot310redis.service;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author CoderJia
 * @create 2024/10/5 下午 05:14
 * @Description
 **/
@Service
public class LockService {

    private final RedissonClient redissonClient;

    public LockService(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public void doSomethingWithLock() {
        // 获取锁对象
        RLock lock = redissonClient.getLock("myLock");

        try {
            // 尝试获取锁,等待时间 100ms,锁定时间 10秒
            if (lock.tryLock(100, 10, TimeUnit.SECONDS)) {
                try {
                    // 加锁成功,执行业务逻辑
                    System.out.println("锁定成功,正在执行关键任务...");
                    Thread.sleep(5000);  // 模拟任务执行
                } finally {
                    // 释放锁
                    lock.unlock();
                    System.out.println("任务完成,已释放锁");
                }
            } else {
                System.out.println("无法获取锁,其他线程正在执行该任务");
            }
        } catch (InterruptedException e) {
            System.out.println(e.getMessage());
        }
    }
}

4. 调用分布式锁

在你的业务逻辑中调用上面创建的 LockService 方法。

java 复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LockController {

    private final LockService lockService;

    public LockController(LockService lockService) {
        this.lockService = lockService;
    }

    @GetMapping("/test-lock")
    public String testLock() {
        lockService.doSomethingWithLock();
        return "分布式锁测试完成";
    }
}

调用 curl "http://localhost:8080/test-lock?id=A" 接口,进入分布式锁执行逻辑。

开启两个线程,同时调用 curl "http://localhost:8080/test-lock?id=A" 和 curl "http://localhost:8080/test-lock?id=B",可以看到先执行的线程占用了锁,第二个线程要等第一个线程释放锁之后才能重新获得锁。

详细说明

  1. RLock :这是 Redisson 提供的分布式锁对象。通过 RedissonClient.getLock() 方法可以获取到一个分布式锁。

  2. tryLock(long waitTime, long leaseTime, TimeUnit unit):此方法尝试获取锁,其中:

    • waitTime 是最大等待时间,表示在该时间内如果未获取到锁则放弃。
    • leaseTime 是锁的自动释放时间,避免因为业务逻辑异常导致锁无法释放。
  3. unlock():业务逻辑执行完后需要手动释放锁,否则其他线程将无法获取锁。

5. 为什么使用Redisson分布式锁

使用 Redisson 实现的分布式锁相对于直接使用 Redis 的分布式锁,具有一些显著的优势,尤其是在功能完善性、开发便捷性以及可扩展性方面。以下是 Redisson 实现的分布式锁相对于手动实现 Redis 分布式锁的几个主要优势:

优势 Redisson 实现分布式锁 手动使用 Redis 实现分布式锁
锁机制支持 可重入锁、公平锁、读写锁等丰富的锁机制 需要手动实现
锁续期机制 自动续期,防止锁超时失效 需要手动续期
操作原子性 内置保证 需要 Lua 脚本保障原子性
易用性 API 简单,易于使用和维护 需要手动编写命令逻辑
部署架构支持 支持单点、哨兵、集群模式 需要手动处理高可用
高级功能 异步、分布式对象、反压支持 需要手动封装
异步和同步支持 完善的异步和反应式支持 需要手动编写异步代码

6. 常见问题

  • 死锁问题 :如果业务逻辑执行时间超过锁的自动释放时间,会导致锁自动释放,其他线程可能会获取锁,造成数据不一致问题。为避免这种情况,可以设置足够长的 leaseTime,或者在业务逻辑完成时手动释放锁。

  • 锁竞争激烈:在高并发场景下,多个线程同时竞争锁,可能会导致部分线程长时间无法获取锁。可以通过优化锁的粒度来减少锁的竞争。

7. 总结

通过 Spring Boot 3 和 Redisson 的结合,你可以轻松实现分布式锁的功能,确保在分布式系统中关键任务的正确执行。Redisson 提供了多种锁的实现,如公平锁、读写锁、可重入锁等,能够满足不同的业务需求。

相关推荐
鶴哥只手遮天13 分钟前
《Redis 8.10.3 深度剖析》系列 · 第 1 章·全景与源码地图:版本谱系、构建体系、全局状态与启动链路
redis·后端·开源
70后写java的老码农26 分钟前
docker-compose 部署 Redis Stack Server 6.2.6-v19
redis·docker
VimorphTech38 分钟前
每批开 4 个线程,为什么限制不住 TTS 的总并发?
java·spring boot·spring
Pniubi42 分钟前
Java为什么要分堆和栈
java·开发语言
杨凯凡1 小时前
Spring Boot 缓存一致性怎么保证?@Cacheable、@CacheEvict 与事务提交时机实战
java·spring boot·spring cache·后端开发·缓存一致性
小南家的青蛙2 小时前
Redis监控与告警体系化实践
redis·监控方案·告警方案
我不会起名字3222 小时前
Redis 从 0 到 1(二十七):JSON 体积是 Protobuf 的 3.7 倍?3 种序列化的 Go 基准测试
redis·go·序列化·protobuf·messagepack
Rain的Java大神之路2 小时前
国家数据集团校招、社招都开了:总部雄安,这些技术岗值得认真看看
java·后端·面试
我不会起名字3222 小时前
Redis 从 0 到 1(二十六):INFO memory 里 8 个关键数字——内存构成与容量规划
redis·容量规划·内存·info·listpack