中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用自定義注解實現redisson分布式鎖

發布時間:2022-02-17 13:49:02 來源:億速云 閱讀:402 作者:iii 欄目:開發技術

這篇文章主要講解了“如何使用自定義注解實現redisson分布式鎖”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何使用自定義注解實現redisson分布式鎖”吧!

自定義注解實現redisson分布式鎖

自定義注解

package com.example.demo.annotation;
import java.lang.annotation.*;
/**
 * desc: 自定義 redisson 分布式鎖注解
 *
 * @author: 邢陽
 * @mail: xydeveloper@126.com
 * @create 2021-05-28 16:50
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Lock {
    /**
     * 鎖的key spel 表達式
     *
     * @return
     */
    String key();
    /**
     * 持鎖時間
     *
     * @return
     */
    long keepMills() default 20;
    /**
     * 沒有獲取到鎖時,等待時間
     *
     * @return
     */
    long maxSleepMills() default 30;
}

aop解析注解

package com.example.demo.utils;
import com.example.demo.annotation.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.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
 * desc: 解析 自定義 redisson 分布式鎖注解
 *
 * @author: 邢陽
 * @mail: xydeveloper@126.com
 * @create 2021-05-28 16:50
 */
@Aspect
@Component
public class LockAspect {
    @Autowired
    private RedissonClient redissonClient;
    /**
     * 用于SpEL表達式解析.
     */
    private final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
    /**
     * 用于獲取方法參數定義名字.
     */
    private final DefaultParameterNameDiscoverer defaultParameterNameDiscoverer = new DefaultParameterNameDiscoverer();
    @Around("@annotation(com.example.demo.annotation.Lock)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object object = null;
        RLock lock = null;
        try {
            // 獲取注解實體信息
            Lock lockEntity = (((MethodSignature) proceedingJoinPoint.getSignature()).getMethod())
                    .getAnnotation(Lock.class);
            // 根據名字獲取鎖實例
            lock = redissonClient.getLock(getKeyBySpeL(lockEntity.key(), proceedingJoinPoint));
            if (Objects.nonNull(lock)) {
                if (lock.tryLock(lockEntity.maxSleepMills(), lockEntity.keepMills(), TimeUnit.SECONDS)) {
                    object = proceedingJoinPoint.proceed();
                } else {
                    throw new RuntimeException();
                }
            }
        } finally {
            if (Objects.nonNull(lock) && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return object;
    }
    /**
     * 獲取緩存的key
     * 
     * key 定義在注解上,支持SPEL表達式
     *
     * @return
     */
    public String getKeyBySpeL(String spel, ProceedingJoinPoint proceedingJoinPoint) {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        String[] paramNames = defaultParameterNameDiscoverer.getParameterNames(methodSignature.getMethod());
        EvaluationContext context = new StandardEvaluationContext();
        Object[] args = proceedingJoinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            context.setVariable(paramNames[i], args[i]);
        }
        return String.valueOf(spelExpressionParser.parseExpression(spel).getValue(context));
    }
}

service中使用注解加鎖使用

/**
 * desc: 鎖
 *
 * @author: 邢陽
 * @mail: xydeveloper@126.com
 * @create 2021-05-28 17:58
 */
@Service
public class LockService {
  	@Lock(key = "#user.id", keepMills = 10, maxSleepMills = 15)
    public String lock(User user) {
        System.out.println("持鎖");
        return "";
    }
}

redisson分布式鎖應用

分布式架構一定會用到分布式鎖。目前公司使用的基于redis的redisson分布式鎖。

應用場景

1.訂單修改操作,首先要獲取該訂單的分布式鎖,能取到才能去操作。lockey可以是訂單的主鍵id。

2.庫存操作,也要按照客戶+倉庫+sku維護鎖定該庫存,進行操作。

代碼:

Redisson管理類

public class RedissonManager {
    private static RedissonClient redisson;
    static {
        Config config = new Config();
        config.useSentinelServers()
                .addSentinelAddress("redis://127.0.0.1:26379","redis://127.0.0.1:7301", "redis://127.0.0.1:7302")
                .setMasterName("mymaster")
                .setReadMode(ReadMode.SLAVE)
                .setTimeout(10000).setDatabase(0).setPassword("123***");
        redisson = Redisson.create(config);
    }
 
    /**
     * 獲取Redisson的實例對象
     * @return
     */
    public static RedissonClient getRedisson(){ return redisson;}
}

分布式鎖

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
public class DistributedLock {
    private static RedissonClient redissonClient = RedissonManager.getRedisson();
    public static boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            return false;
        }
    }
    public static void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.unlock();
    }
}

測試類

public class RedissonTest {
    public static void main(String[] args) throws Exception{
        Thread.sleep(2000L);
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    //tryLock,第三個參數是等待時間,5秒內獲取不到鎖,則直接返回。 第四個參數 30是30秒后強制釋放
                    boolean hasLock = DistributedLock.tryLock("lockKey", TimeUnit.SECONDS,5,30);
                    //獲得分布式鎖
                    if(hasLock){
                        System.out.println("idea1: " + Thread.currentThread().getName() + "獲得了鎖");
                       
                    /**
                         * 由于在DistributedLock.tryLock設置的等待時間是5s,
                         * 所以這里如果休眠的小于5秒,這第二個線程能獲取到鎖,
                         *  如果設置的大于5秒,則剩下的線程都不能獲取鎖。可以分別試試2s,和8s的情況
                         */
                        Thread.sleep(10000L);
                        DistributedLock.unlock("lockKey");
                    } else {
                        System.out.println("idea1: " + Thread.currentThread().getName() + "無法獲取鎖");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } 
            }) .start();
        }
    }
}

我們再打開一個idea,可以把代碼復制一份。同事啟動兩個RedissonTest ,模擬了并發操作。

測試結果:

idea2: Thread-1獲得了鎖
idea2: Thread-0無法獲取鎖
idea2: Thread-2無法獲取鎖
 
 
idea1: Thread-2無法獲取鎖
idea1: Thread-0無法獲取鎖
idea1: Thread-1無法獲取鎖

從測試結果發現,最后是只能有一個idea的一個線程能獲取到鎖。

感謝各位的閱讀,以上就是“如何使用自定義注解實現redisson分布式鎖”的內容了,經過本文的學習后,相信大家對如何使用自定義注解實現redisson分布式鎖這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

商都县| 张掖市| 澎湖县| 澄城县| 铜川市| 高台县| 南投县| 清水河县| 利辛县| 宁阳县| 大新县| 喜德县| 澄江县| 个旧市| 文登市| 宣恩县| 绍兴市| 望奎县| 伊吾县| 沂源县| 成安县| 汨罗市| 晋城| 连城县| 长汀县| 洪雅县| 辽中县| 南平市| 开封市| 荥经县| 怀来县| 来安县| 黄梅县| 中方县| 新龙县| 巫溪县| 昂仁县| 苍溪县| 桂林市| 海阳市| 龙游县|