重学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 提供了多种锁的实现,如公平锁、读写锁、可重入锁等,能够满足不同的业务需求。

相关推荐
禁默24 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood31 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Code哈哈笑33 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
gb421528736 分钟前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端
程序猿进阶37 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
zfoo-framework44 分钟前
【jenkins插件】
java
风_流沙1 小时前
java 对ElasticSearch数据库操作封装工具类(对你是否适用嘞)
java·数据库·elasticsearch
亽仒凣凣1 小时前
Windows安装Redis图文教程
数据库·windows·redis
ProtonBase1 小时前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构