Heim  >  Artikel  >  Java  >  So verwenden und implementieren Sie die Funktion der verteilten Sperre Java-Redis-Redisson

So verwenden und implementieren Sie die Funktion der verteilten Sperre Java-Redis-Redisson

PHPz
PHPznach vorne
2023-05-14 21:55:04728Durchsuche

Front-End

Wir haben die Java-Redis-Redisson-Konfiguration geändert, um die Verwendung von Sperren komfortabler zu gestalten

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 RedissonLock {
    int lockTime() default 3; //加锁的时间默认3秒,  如果任务在3秒内执行完毕那么自动释放锁,如果任务3秒内没有执行完毕也会释放锁, 所以内容执行时间过长适当加大锁的时间
    String key() default "" ;  //唯一标识,如果没有那么默认为token->sessionId
    String doc() default "重复提交请求,请稍后再试";
    boolean repeatLock() default false; //可重复加锁直到加锁成功,默认为false不能重复加锁
    int repeatLockCount() default -1; //可重复加锁限制加锁的次数, 默认-1直到成功,设置10那么加锁10次都没成功就直接返回
    int lockWaitTimeMs() default 100; //重复加锁默认的阻塞时间100毫秒,可以自己定义
}

Funktionsnutzung Und Einführung

Unterstützt Konfigurationssperrzeit

Unterstützt Konfigurationssperrschlüssel (Anfragen für denselben Schlüssel werden gesperrt)

Unterstützt wiederholtes Sperren

  • Unterstützt die Anzahl wiederholter Sperren

  • Unterstützt die Intervall zwischen wiederholten Sperren

  • Durch die Kombination der oben genannten Funktionen können Idempotenz, verteiltes pessimistisches Sperren und Timeout-Verwerfen erreicht werden. Es wird nicht nur im Controller verwendet, sondern wird auch in allen Spring-basierten Containerverwaltungs-Beans unterstützt . Wenn es spezielle Szenarien gibt, können wir die Sperre jederzeit direkt aufheben

    import com.application.Result;
    import com.commonutils.NullUtils;
    import com.redis.utils.DistributedRedisLock;
    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 org.springframework.util.Assert;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import javax.servlet.http.HttpServletRequest;
    @Aspect
    @Component
    public class RepeatSubmitAspect {
        @Value("${spring.redis.redisson.tokenName}")
        private  String tokenName;
        @Autowired
        private DistributedRedisLock redisLock;
        @Pointcut("@annotation(noRepeatSubmit)")
        public void pointCut(RedissonLock noRepeatSubmit) {
        }
        public static HttpServletRequest getRequest() {
            ServletRequestAttributes ra= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            return ra.getRequest();
        }
        @Around("pointCut(noRepeatSubmit)")
        public Object around(ProceedingJoinPoint pjp, RedissonLock noRepeatSubmit) throws Throwable {
            int lockSeconds = noRepeatSubmit.lockTime();
            String doc = noRepeatSubmit.doc();
            String keyName = noRepeatSubmit.key();
            boolean b = noRepeatSubmit.repeatLock();
            int repeatLockCount = noRepeatSubmit.repeatLockCount();
            int lockWaitTimeMs = noRepeatSubmit.lockWaitTimeMs();
            HttpServletRequest request = getRequest();
            Assert.notNull(request, "request can not null");
            //如果没有唯一表示那么就使用token或者sessionID来唯一表示
            if(!NullUtils.notEmpty(keyName)){
                String token = request.getHeader(tokenName);
                if(NullUtils.notEmpty(token)){
                    keyName=token;
                }else{
                    //使用sessionID (注意保证分布式session共享)
                    keyName = request.getSession().getId();
                }
                System.out.println("tokenName:"+keyName);
            }
            String path = request.getServletPath();
            String key = getKey(keyName, path);
            //加锁
            boolean isSuccess = redisLock.acquire(key, lockSeconds,b,repeatLockCount,lockWaitTimeMs);
            if (isSuccess) {
                // 获取锁成功
                Object result;
                try {
                    // 执行
                    result = pjp.proceed();
                } finally {
                    // 解锁
                    redisLock.release(key);
                }
                return result;
            } else {
                // 获取锁失败,认为是重复提交的请求
                return Result.Error(doc);
            }
        }
        private String getKey(String token, String path) {
            return token + path;
        }
    }

    Überprüfungsmethode: Verwenden Sie Jmeter-Multithreading-10000-Anfragen Bei der Verwendung von jmeter müssen wir manuell einen Schlüssel hinzufügen oder einen Token verwenden, um den Effekt zu überprüfen, da die Sitzungs-ID jedes Mal anders ist

Das obige ist der detaillierte Inhalt vonSo verwenden und implementieren Sie die Funktion der verteilten Sperre Java-Redis-Redisson. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen