通过切面类对方法添加分布式redis锁demo

1、创建注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface RedisLock {
    /** 活动key */
    String activityKey() default "";

    /** 锁存储字符串 */
    String valueStr() default "1";

    /** 有效期,默认1 */
    long timeout() default 1;

    /** 有效期单位,默认秒 */
    TimeUnit timeUnit() default TimeUnit.SECONDS;

    /** 是否在方法执行完成后删除 */
    boolean overDel() default true;
}

2、创建切面类

/**
 * 使用redis锁注解对方法加锁
 * @author lei.yan004
 */
@Component
@Aspect
public class RedisLockAspect {

    private static final Logger logger = LoggerFactory.getLogger(RedisLockAspect.class);

    @Autowired
    private RedisUtil redisUtil;

    // 声明公共切入点
    @Pointcut("@annotation(com.sinolife.lock.RedisLock)")
    private void lockPointCut() {
    }

    /**
     * 方法执行前调用,用于请求加锁
     * @param joinPoint
     * @return
     */
    @Around(value = "lockPointCut()")
    public Object lockAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RedisLock annotation = method.getAnnotation(RedisLock.class);

        String userId = PlatformContext.currentUser();
        if (StringUtil.isDataEmpty(userId)) {
            return ResponseResult.fail("登陆超时,请重新登陆");
        }
        String redisKey = RedisKeyConstant.REDIS_KEY_PUB_LIMIT ;
        if(StringUtils.isNotBlank(annotation.activityKey())){
            redisKey += annotation.activityKey() + ":" ;
        }
        redisKey += method.getName() + ":" + userId;
        boolean setResult = redisUtil.setIfAbsent(redisKey, annotation.valueStr(), annotation.timeout(), annotation.timeUnit());
        if (!setResult) {
            return ResponseResult.fail("正在处理中,请勿重复操作");
        }
        return joinPoint.proceed();
    }

    /**
     * 方法执行完成后调用,用于释放锁
     * @param joinPoint
     * @return
     * @Author lei.yan004
     */
    @After("lockPointCut()")
    public void lockAfter(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RedisLock annotation = method.getAnnotation(RedisLock.class);
        if (annotation.overDel()) {
            String userId = PlatformContext.currentUser();
            String redisKey = RedisKeyConstant.REDIS_KEY_PUB_LIMIT;
            if (StringUtils.isNotBlank(annotation.activityKey())) {
                redisKey += annotation.activityKey() + ":";
            }
            redisKey += method.getName() + ":" + userId;
            redisUtil.delete(redisKey);
        }
    }
}

3、使用demo

可以通过RedisLock注解的属性,进行一些自定义的配置,例如有效期等

@RedisLock
@RequestMapping("/updateScene")
public ResponseResult<Map<String,Object>> updateScene() {
	...
}
Redis 分布式锁是一种在分布式环境下使用 Redis 实现的定机制,可以避免多个客户端同时修改共享资源而导致数据不一致的情况。下面是一个简单的 Redis 分布式锁的代码示例: ```python import redis import time # 连接 Redis 数据库 r = redis.StrictRedis(host='localhost', port=6379, db=0) # 加函数 def acquire_lock(lockname, acquire_timeout=10, lock_timeout=10): identifier = str(time.time()) end = time.time() + acquire_timeout while time.time() < end: if r.setnx(lockname, identifier): r.expire(lockname, lock_timeout) return identifier return False # 释放函数 def release_lock(lockname, identifier): pipe = r.pipeline(True) while True: try: pipe.watch(lockname) if pipe.get(lockname) == identifier: pipe.multi() pipe.delete(lockname) pipe.execute() return True pipe.unwatch() break except redis.exceptions.WatchError: pass return False # 使用分布式锁 def demo(): lockname = "mylock" identifier = acquire_lock(lockname) if not identifier: print("无法获取") return print("成功获取") # 在此进行需要加的操作 release_lock(lockname, identifier) print("释放成功") demo() ``` 以上代码示例中,首先连接 Redis 数据库,然后定义了获取和释放的两个函数。在使用分布式锁的示例中,先调用 `acquire_lock` 获取,成功获取之后进行需要加的操作,完成操作后调用 `release_lock` 释放。这样可以保证在多个客户端同时请求时,只有一个客户端能够成功获取,从而避免了数据的并发修改问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值