Springboot2.X整合redisson实现分布式锁

1.添加依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2.添加配置类:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * redisson bean管理
 */
@Configuration
public class RedissonConfig {

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private String redisPost;

    @Value("${spring.redis.password}")
    private String redisPassword;

    /**
     * Redisson客户端注册
     * 单机模式
     */
    @Bean(destroyMethod = "shutdown")
    public RedissonClient createRedissonClient(){
        //读取配置,官方参考地址:https://github.com/redisson/redisson
        Config config = new Config();
        SingleServerConfig singleServerConfig = config.useSingleServer();
        singleServerConfig.setAddress("redis://" + redisHost + ":" + redisPost);
        singleServerConfig.setPassword(redisPassword);
        singleServerConfig.setTimeout(3000);
        //放置redis第二个桶
        singleServerConfig.setDatabase(1);
        return Redisson.create(config);
    }

    @Bean
    public RedissonDistributedLockImpl redissonLocker(RedissonClient redissonClient) {
        RedissonDistributedLockImpl locker = new RedissonDistributedLockImpl(redissonClient);
        return locker;
    }

}

3.添加自定义注解类:

3.1annotation:

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedissonLock {

}

3.2aspect:

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 基于redis的redisson客户端实现分布式锁
 *
 */
@Aspect
@Component
@Slf4j
public class RedissonLockAspect {

    public static final int WAIT_GET_LOCK_TIME = 3000;

    public static final int WAIT_RELEASE_LOCK_TIME = 5000;

    @Autowired
    private IRedissonDistributedLock iRedissonDistributedLock;

    @Value("${spring.application.name}")
    private String serverName;

    /**
     * 切点
     */
    @Pointcut("@annotation(com.xx.xx.xx.redis.redisson.aspect.annotation.RedissonLock)")
    public void redissonLockPoint() {
    }

    /**
     *
     * @param point 代表当前正在运行的方法
     * @return Object 结果
     * @throws Throwable e
     */
    @Around("redissonLockPoint()")
    public Object checkLock(ProceedingJoinPoint point) throws Throwable {
        //当前线程名称
        String threadName = Thread.currentThread().getName();
        //获取当前类名
        Object className = point.getTarget().getClass().getName();
        //拦截的方法名称
        String methodName = point.getSignature().getName();
        log.info("当前线程:{}------进入分布式锁AOP------", threadName);
        //生成分布式锁:服务名+类名+方法名
        String lockRedisKey = serverName + ":" + className + ":" + methodName;
        log.info("当前线程:{},分布式锁的key:{}", threadName, lockRedisKey);
        //获取锁3000等到获取锁的时间,leaseTime 获取锁后持有时间时间,单位 MILLISECONDS:毫秒
        if (iRedissonDistributedLock.tryLock(lockRedisKey, WAIT_GET_LOCK_TIME, WAIT_RELEASE_LOCK_TIME, TimeUnit.MILLISECONDS)) {
            try {
                log.info("当前线程:{},获取锁成功", threadName);
                return point.proceed();
            } catch (Throwable throwable) {
                throw new Exception(throwable);
            } finally {
                if (iRedissonDistributedLock.isLocked(lockRedisKey)) {
                    log.info("当前线程:{}, key:{},对应的锁被线程持有", threadName, lockRedisKey);
                    if (iRedissonDistributedLock.isHeldByCurrentThread(lockRedisKey)) {
                        log.info("当前线程:{},key:{},保持锁定", threadName, lockRedisKey);
                        iRedissonDistributedLock.unlock(lockRedisKey);
                        log.info("当前线程:{},key:{},释放锁", threadName, lockRedisKey);
                    }
                }
            }
        } else {
            log.info("当前线程:{},获取锁失败", threadName);
            //这里return可以根据自己业务改造,我这里是返回“系统繁忙,请稍后再试!”
            return Result.error(AppErrorCodeEnum.SYSTEM_BUSY.getMessage());
        }
    }
}

4.添加redisson客户端类:

4.1接口:

import java.util.concurrent.TimeUnit;

public interface IRedissonDistributedLock {

    /**
     * 加锁
     * @param lockKey key
     */
    void lock(String lockKey);

    /**
     * 加锁锁,设置有效期
     *
     * @param lockKey key
     * @param timeout 有效时间,默认时间单位在实现类传入
     */
    void lock(String lockKey, int timeout);

    /**
     * 加锁,设置有效期并指定时间单位
     * @param lockKey key
     * @param timeout 有效时间
     * @param unit    时间单位
     */
    void lock(String lockKey, int timeout, TimeUnit unit);

    /**
     * 释放锁
     *
     * @param lockKey key
     */
    void unlock(String lockKey);

    /**
     * 尝试获取锁,获取到则持有该锁返回true,未获取到立即返回false
     * @param lockKey 锁
     * @return true-获取锁成功 false-获取锁失败
     */
    boolean tryLock(String lockKey);

    /**
     * 尝试获取锁,获取到则持有该锁leaseTime时间.
     * 若未获取到,在waitTime时间内一直尝试获取,超过waitTime还未获取到则返回false
     * @param lockKey   key
     * @param waitTime  尝试获取时间
     * @param leaseTime 锁持有时间
     * @param unit      时间单位
     * @return true-获取锁成功 false-获取锁失败
     * @throws InterruptedException e
     */
    boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit)
            throws InterruptedException;

    /**
     * 锁是否被任意一个线程锁持有
     * @param lockKey 锁
     * @return true-被锁 false-未被锁
     */
    boolean isLocked(String lockKey);

    /**
     * isHeldByCurrentThread()的作用是查询当前线程是否保持此锁定
     * @param lockKey 锁
     * @return true or false
     */
    boolean isHeldByCurrentThread(String lockKey);

}

4.2实现:

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import java.util.concurrent.TimeUnit;

/**
 * redisson实现分布式锁接口
 */
public class RedissonDistributedLockImpl implements IRedissonDistributedLock {

    private final RedissonClient redissonClient;

    /**
     * 构造方法 赋予本类的redisClient以实例
     * @param redissonClient client
     */
    public  RedissonDistributedLockImpl(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    @Override
    public void lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
    }

    @Override
    public void lock(String lockKey, int leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(leaseTime, TimeUnit.MILLISECONDS);
    }

    @Override
    public void lock(String lockKey, int timeout, TimeUnit unit) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(timeout, unit);
    }

    @Override
    public void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.unlock();
    }

    @Override
    public boolean tryLock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        return lock.tryLock();
    }

    @Override
    public boolean tryLock(String lockKey, long waitTime, long leaseTime,
                           TimeUnit unit) throws InterruptedException {
        RLock lock = redissonClient.getLock(lockKey);
        return lock.tryLock(waitTime, leaseTime, unit);
    }

    @Override
    public boolean isLocked(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        return lock.isLocked();
    }

    @Override
    public boolean isHeldByCurrentThread(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        return lock.isHeldByCurrentThread();
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值