开发者社区> mazhen1991> 正文

注解的方式实现redis分布式锁

简介: 创建redisLock注解: import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.
+关注继续查看

创建redisLock注解:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;

/**
 * redis锁注解
 * @author MAZHEN
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface RedisLock {
    String lockPrefix() default "";
    long timeOut() default 60;
    TimeUnit timeUnit() default TimeUnit.SECONDS;
}

拦截器逻辑:

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.apache.bcel.classfile.Constant;
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.stereotype.Component;
import org.springframework.util.StringUtils;

import com.spring.mongo.annotation.RedisLock;

/**
 * redis锁拦截器实现
 * @author MAZHEN
 */
@Aspect
@Component
public class RedisLockInterceptor {

    private static final Integer MAX_RETRY_COUNT = 10;
    private static final String LOCK_PRE_FIX = "lockPreFix";
    private static final String TIME_OUT = "timeOut";

    @Autowired
    private RedisManager redisManager;

    @Pointcut("@annotation(com.spring.mongo.annotation.RedisLock)")
    public void redisLockAspect(){}

    @Around("redisLockAspect()")
    public Map<String, Object> lockAroundAction(ProceedingJoinPoint proceeding){
        //获取redis锁
        Map<String, Object> getLockResult = this.getLock(proceeding,0,System.currentTimeMillis());
    }

    /**
     * 获取锁
     * @param proceeding
     * @return
     */
    private Map<String, Object> getLock(ProceedingJoinPoint proceeding,int count,long currentTime){
        //获取注解中的参数
        Map<String, Object> annotationArgs = this.getAnnotationArgs(proceeding);
        String lockPrefix = (String) annotationArgs.get(LOCK_PRE_FIX);
        long expire = (long) annotationArgs.get(TIME_OUT);
        String key = this.getFirstArg(proceeding);
        if(StringUtils.isEmpty(lockPrefix) || StringUtils.isEmpty(key)){
            return this.argErrResult("锁前缀或业务参数不能为空");
        }
        String lockName = lockPrefix+"_"+key;
        String value = String.valueOf(currentTime);
        if(CommonRedisUtils.setNx(lockName,value) == 1){
            //获取锁成功
            CommonRedisUtils.expire(lockName,expire);
            return this.buildSuccessResult();
        }else {
            //获取锁失败,为防止其它线程正在设置过时时间时误删,添加第一个条件
            if((System.currentTimeMillis()-currentTime>5000)
                    &&(CommonRedisUtils.ttl(lockName)<0
                            ||System.currentTimeMillis()-currentTime>expire)){
                //强制删除锁,并尝试再次获取锁
                CommonRedisUtils.delete(lockName);
                if(count<MAX_RETRY_COUNT){
                    return getLock(proceeding,count++,currentTime);
                }
            }
            return this.buildGetLockErrorResult("请重试!!!");
        }
    }

    /**
     * 获取锁参数
     * @param proceeding
     * @return
     */
    private Map<String, Object> getAnnotationArgs(ProceedingJoinPoint proceeding){
        Class target = proceeding.getTarget().getClass();
        Method[] methods = target.getMethods();
        String methodName = proceeding.getSignature().getName();
        for (Method method : methods) {
            if(method.getName().equals(methodName)){
                Map<String, Object> result = new HashMap<String, Object>();
                RedisLock redisLock = method.getAnnotation(RedisLock.class);
                result.put(LOCK_PRE_FIX,redisLock.lockPrefix());
                result.put(TIME_OUT, redisLock.timeUnit().toSeconds(redisLock.timeOut()));
                return result;
            }
        }
        return null;
    }

    /**
     * 获取第一个String类型的参数为锁的业务参数
     * @param proceeding
     * @return
     */
    public String getFirstArg(ProceedingJoinPoint proceeding){
        Object[] args = proceeding.getArgs();
        if(args != null && args.length>0){
            for (Object object : args) {
                String type = object.getClass().getName();
                if("java.lang.String".equals(type)){
                    return (String)object;
                }
            }
        }
        return null;
    }

    public Map<String, Object> argErrResult(String mes){
        Map<String, Object> result = new HashMap<String, Object>();
        //TODO
        //result.put("code", "9");
        result.put("msg", mes);
        return result;
    }

    public Map<String, Object> buildGetLockErrorResult(String mes){
        Map<String, Object> result = new HashMap<String, Object>();
        //TODO
        //result.put("code", "9");
        result.put("msg", mes);
        return result;
    }

    public Map<String, Object> buildSuccessResult(){
        Map<String, Object> result = new HashMap<String, Object>();
        //TODO
        //result.put("code", "1");
        result.put("msg", "处理成功");
        return result;
    }
}

使用方式:只需要在需要使用redis锁的方法上添加@RedisLock注解,并输入redis锁的前缀字段,过时时间和时间单位有默认值,而方法上的第一个String类型的参数为锁的key的第二段。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Redis实现分布式锁的几种方案
Redis实现分布式锁的几种方案
22 0
使用注解实现redis分布式锁
使用注解实现redis分布式锁
40 0
被问烂的Redis分布式锁,你真的懂了? 下
被问烂的Redis分布式锁,你真的懂了? 下
30 0
被问烂的Redis分布式锁,你真的懂了? 上
被问烂的Redis分布式锁,你真的懂了?上
28 0
因Redis分布式锁造成的S1级重大事故,整个团队都没年终奖了。。。
因Redis分布式锁造成的S1级重大事故,整个团队都没年终奖了。。。
33 0
Redis分布式锁真的安全吗?
Redis分布式锁真的安全吗?
931 0
突击Redis重大事故现场,又是“分布式锁”惹的祸
基于Redis使用分布式锁在当今已经不是什么新鲜事了。本篇文章主要是基于我们实际项目中因为redis分布式锁造成的事故分析及解决方案。 背景:我们项目中的抢购订单采用的是分布式锁来解决的。有一次,运营做了一个飞天茅台的抢购活动,库存100瓶,但是却超卖了!要知道,这个地球上飞天茅台的稀缺性啊!!!事故定为P0级重大事故...只能坦然接受。整个项目组被扣绩效了~~事故发生后,CTO指名点姓让我带头冲锋来处理,好吧,冲~
30 0
哦哟!才知道,原来大厂的Redis分布式锁都这么设计
常用的即 synchronize 或 Lock 等 JDK 自带的锁,只能锁住当前进程,仅适用于单体架构服务。 而在分布式多服务实例场景下必须使用分布式锁
41 0
面试官:Redis分布式锁超时了,任务还没执行完怎么办?
今天主要分享的是面试中常见的redis的一些面试内容。如果你正好需要刚好可以帮你回顾一下,如果不需要可以收藏起来后面用到的时候翻出来回顾。
185 0
【实战企业级Java二】渐进式理解Redis分布式锁
渐进式理解Redis分布式锁。分布式锁需要满足的条件互斥性、同一性、可重入性、容错性,四个条件的含义,为什么需要这个条件,如何理解分布式锁
22702 0
基于redis的分布式锁
基于redis的分布式锁
53 0
【Redis的那些事 · 上篇】Redis的介绍、五种数据结构演示和分布式锁
Redis,全称是Remote Dictionary Service,翻译过来就是,远程字典服务。redis属于nosql非关系型数据库。Nosql常见的数据关系,基本上是以key-value键值对形式存在的。Key-value: 就像翻阅中文字典或者单词字典,通过指定的需要查询的字或者单词(key),可以查找到字典里面对应的详细内容和介绍(value)
64 0
Redis 实现分布式锁
分布式锁,主要考察使用者对原子性的理解,原子性可以保证程序从异常中恢复后,redis中的数据是正确的,程序依然正常运行。分布式锁是实现线程同步手段之一。
69 0
Redis(三十二)-用Redis做分布式锁
随着业务发展的需要,原有的单机部署的系统逐渐演变成了分布式集群系统,由于分布式系统多线程,多进程分布在不同的机器上,这使得原有的并发控制策略失效,单纯的Java API并不能提供分布式锁的能力(就是Java中的本地锁Lock以及synchronized)。 为了解决这个问题就需要一种能跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题。
61 0
详解Redis,Redis缓存,Redis分布式锁(2)
详解Redis,Redis缓存,Redis分布式锁(2)
84 0
+关注
mazhen1991
大数据,元计算专家
文章
问答
视频
相关电子书
更多
Redis Cluster的基本原理
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载