Spring Boot中使用Redisson实现分布式锁

在分布式系统中,确保多个进程或线程对共享资源的互斥访问是一个重要的需求。Redisson是一个高效的Redis客户端,它提供了丰富的分布式对象和服务,包括分布式锁。本文将详细介绍如何在Spring Boot中使用Redisson实现分布式锁。

一、Redisson简介

Redisson是一个基于Redis的Java客户端,提供了对Redis常用数据结构的便捷操作。它的分布式锁功能强大,支持多种锁类型,包括可重入锁、公平锁、读写锁等,适合在分布式系统中使用。

二、集成Redisson

2.1 引入依赖

在Spring Boot项目的 pom.xml中添加Redisson的依赖:

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.16.5</version>
</dependency>
2.2 配置Redisson

创建一个配置类 RedissonConfig,配置Redisson客户端:

package com.example.demo.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {

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

三、实现分布式锁

3.1 使用Redisson分布式锁

在需要加锁的方法中使用Redisson提供的分布式锁。以下示例展示了如何使用Redisson实现一个简单的分布式锁功能:

package com.example.demo.service;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class LockService {

    @Autowired
    private RedissonClient redissonClient;

    public void performTaskWithLock() {
        RLock lock = redissonClient.getLock("myLock");
        boolean isLocked = false;
        try {
            // 尝试获取锁,最多等待100秒,上锁后10秒自动解锁
            isLocked = lock.tryLock(100, 10, TimeUnit.SECONDS);
            if (isLocked) {
                // 执行需要加锁的业务逻辑
                System.out.println("Lock acquired, executing task...");
                Thread.sleep(8000); // 模拟任务执行时间
            } else {
                System.out.println("Could not acquire lock");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (isLocked) {
                lock.unlock();
                System.out.println("Lock released");
            }
        }
    }
}
3.2 使用注解实现分布式锁

为了简化锁的使用,可以通过自定义注解和AOP实现分布式锁。首先定义一个注解 @DistributedLock:

package com.example.demo.annotation;

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 value() default "distributed-lock";
    long waitTime() default 100;
    long leaseTime() default 10;
    TimeUnit timeUnit() default TimeUnit.SECONDS;
}

然后创建一个AOP切面类 DistributedLockAspect,在方法调用前后处理锁的逻辑:

package com.example.demo.aspect;

import com.example.demo.annotation.DistributedLock;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class DistributedLockAspect {

    @Autowired
    private RedissonClient redissonClient;

    @Around("@annotation(distributedLock)")
    public Object around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) throws Throwable {
        RLock lock = redissonClient.getLock(distributedLock.value());
        boolean isLocked = false;
        try {
            isLocked = lock.tryLock(distributedLock.waitTime(), distributedLock.leaseTime(), distributedLock.timeUnit());
            if (isLocked) {
                return joinPoint.proceed();
            } else {
                throw new RuntimeException("Could not acquire lock");
            }
        } finally {
            if (isLocked) {
                lock.unlock();
            }
        }
    }
}

在需要加锁的方法上使用注解 @DistributedLock:

package com.example.demo.service;

import com.example.demo.annotation.DistributedLock;
import org.springframework.stereotype.Service;

@Service
public class AnnotatedLockService {

    @DistributedLock(value = "annotatedLock", waitTime = 50, leaseTime = 5, timeUnit = TimeUnit.SECONDS)
    public void performTaskWithAnnotatedLock() {
        System.out.println("Lock acquired with annotation, executing task...");
        try {
            Thread.sleep(3000); // 模拟任务执行时间
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Task completed");
    }
}

分析说明表

步骤 说明 示例代码
引入依赖 在项目的 pom.xml中添加Redisson依赖 <dependency>...</dependency>
配置Redisson 创建配置类,配置Redisson客户端 Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redisson = Redisson.create(config);
使用分布式锁 在需要加锁的方法中使用Redisson的分布式锁 RLock lock = redissonClient.getLock("myLock");
使用注解实现分布式锁 定义注解 @DistributedLock和AOP切面类 DistributedLockAspect @Around("@annotation(distributedLock)")
注解使用示例 在需要加锁的方法上使用注解 @DistributedLock @DistributedLock(value = "annotatedLock", waitTime = 50, leaseTime = 5, timeUnit = TimeUnit.SECONDS)

总结

通过Redisson,开发者可以在Spring Boot应用中轻松实现分布式锁,确保多个进程或线程对共享资源的互斥访问。本文介绍了如何在Spring Boot项目中集成Redisson,使用分布式锁,并通过自定义注解和AOP简化锁的使用。Redisson不仅提供了便捷的API,还支持多种锁类型,适合在复杂的分布式系统中应用。希望本文能够为您在实际项目中实现分布式锁提供有价值的参考和帮助。