SpringBoot与Redisson整合,用注解方式解决分布式锁的使用问题

Redisson 是一个基于 Redis 的 Java 客户端,提供了丰富的分布式锁功能,如红锁(Red Lock)、公平锁、可重入锁等。Redisson 的设计使得开发者可以非常方便地在 Spring Boot 项目中集成这些功能,而不需要深入了解底层的实现细节。

特点

  • 支持多种类型的分布式锁。
  • 内置了读写锁、信号量等功能。
  • 提供了简单的 API 和强大的容错机制。
  • 可以通过注解的方式简化锁的使用。

常见应用场景

  1. 分布式锁:确保多个服务实例不会同时修改共享资源。
  2. 分布式对象:跨多个 JVM 实例共享数据结构(如列表、集合、队列、地图)。
  3. 分布式消息队列:构建发布/订阅模式的消息传递系统。
  4. 分布式任务调度:安排定时任务或一次性任务,并确保同一时间只有一个节点执行特定任务。
  5. 分布式计数器:统计访问次数、点击量等指标,适用于高并发环境。

代码实操

通过自定义注解和切面(AOP)来简化锁的使用,并确保线程安全。

1. 添加依赖

首先,在 pom.xml 中添加 Redisson 和 Spring Boot Starter 的依赖:

<dependencies>
    <!-- Spring Boot Starter for Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Redisson Dependency -->
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson-spring-boot-starter</artifactId>
        <version>3.17.6</version> <!-- 请根据需要调整版本 -->
    </dependency>
</dependencies>

2. 配置 Redisson

创建 application.yml 文件配置 Redis 连接信息:

spring:
  redis:
    host: localhost
    port: 6379
    password: your_password_if_any

# Redisson configuration
redisson:
  single-server-address: redis://@localhost:6379

3. 创建自定义注解和切面

自定义注解

定义一个自定义注解 @DistributedLock,用于标记需要加锁的方法。

package com.example.demo.lock;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DistributedLock {
    String lockName();
}

切面类

创建一个切面类 DistributedLockAspect 来处理加锁和解锁逻辑。

package com.example.demo.lock;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Aspect
@Component
publicclass DistributedLockAspect {

    @Autowired
    private RedissonClient redissonClient;

    @Around("@annotation(com.example.demo.lock.DistributedLock)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        DistributedLock annotation = signature.getMethod().getAnnotation(DistributedLock.class);
        String lockName = annotation.lockName();

        RLock lock = redissonClient.getLock(lockName);

        try {
            // 尝试获取锁,最多等待10秒,持有锁的时间为30秒
            if (!lock.tryLock(1030, TimeUnit.SECONDS)) {
                thrownew RuntimeException("Failed to acquire lock.");
            }

            return joinPoint.proceed();
        } finally {
            // 确保在任何情况下都能释放锁
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}

4. 创建测试控制器

创建一个简单的控制器 LockController 来测试分布式锁的功能。

package com.example.demo.controller;

import com.example.demo.lock.DistributedLock;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
publicclass LockController {

    privateint counter = 0;

    @GetMapping("/increment")
    @DistributedLock(lockName = "counterLock")
    public String incrementCounter() {
        counter++;
        return"Counter value: " + counter;
    }
}

5. 测试结果

为了验证注解式分布式锁的效果,可以通过模拟高并发请求来测试 /increment 接口。可以使用 Apache Bench (ab) 或者其他负载测试工具来发送大量并发请求到该接口。

我们在本地环境中启动了 Spring Boot 应用程序,并且 Redis 服务器也运行正常。然后执行如下命令进行测试:

ab -n 100 -c 10 http://localhost:8080/increment

这条命令表示发送100个请求,每个批次10个并发请求。

  • 每次请求都应该成功返回一个新的计数值,没有出现重复值。
  • 即使有多个请求几乎同时到达,由于分布式锁的存在,它们会被顺序化执行,保证了线程安全。

总结

基于注解的分布式锁功能,并且通过切面编程(AOP)简化了锁的管理逻辑。这种方法不仅提高了代码的可读性和维护性,还确保了在高并发环境下对共享资源的安全访问。

关注我,送Java福利

/**
 * 这段代码只有Java开发者才能看得懂!
 * 关注我微信公众号之后,
 * 发送:"666"
 * 即可获得一本由Java大神一手面试经验诚意出品
 * 《Java开发者面试百宝书》Pdf电子书
 * 福利截止日期为2025年01月22日止
 * 手快有手慢没!!!
*/
System.out.println("请关注我的微信公众号:");
System.out.println("Java知识日历");




原文始发于微信公众号(Java知识日历):SpringBoot与Redisson整合,用注解方式解决分布式锁的使用问题

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/310646.html

(0)
服务端技术精选的头像服务端技术精选

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!