基于Redisson的分布式锁

1. 依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.27.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2. 实现

2.1 锁注解

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

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RLock {

    String key();
}

2.2 RedissonConfig

import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@ConfigurationProperties(prefix = "spring.redis")
@Configuration
@Data
public class RedissonConfig {

    // 读取配置文件里面的Redis信息
    private String host;
    private String port;
    private String password;

    /**
     * 配置redisson
     */
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() {
        Config config = new Config();
        String address = "redis://" + host + ":" + port;
        //使用json序列化方式
        config.setCodec(new JsonJacksonCodec());
        config.useSingleServer().setAddress(address).setPassword(password);
        return Redisson.create(config);
    }

}

2.3 AOP切面, 拦截需要使用锁的方法

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.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;

@Component
@Aspect
public class RLockAspect {

    @Resource
    private RedissonClient redissonClient;

    @Around("@annotation(rLock)")
    public Object before(ProceedingJoinPoint point, RLock rLock){
        String key = rLock.key();
        Object proceed = null;
        org.redisson.api.RLock lock = null;
        try {
        	// 获取锁
            lock = redissonClient.getLock(key);
            // 尝试加锁
            if (lock.tryLock()) {
            	// 加锁成功, 执行目标方法
                proceed = point.proceed();
            } else {
                MethodSignature methodSignature = (MethodSignature) point.getSignature();
                // 获取方法
                Method method = methodSignature.getMethod();
                System.out.println("该方法没有执行--> " + method.getName());
            }
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally { // 释放锁
            // 解锁前检查当前线程是否持有该锁
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return proceed;
    }
}

3. 测试

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class TimerTest {

    @RLock(key = "cn:ac:zing:lock:test")
    @Scheduled(cron = "0/10 * * * * ?")
    public void lock1() {
        String date = LocalDateTime.now().toString();
        System.out.println(date + " lock1 执行");
    }

    @RLock(key = "cn:ac:zing:lock:test")
    @Scheduled(cron = "0/10 * * * * ?")
    public void lock2() {
        String date = LocalDateTime.now().toString();
        System.out.println(date + " lock2 执行");
    }
}

控制台输出:
在这里插入图片描述

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值