温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

redis分布式锁解决集群服务器定时任务重复执行问题

发布时间:2020-06-20 08:18:48 来源:网络 阅读:946 作者:wx5d30212829a35 栏目:编程语言

问题描述

将带有定时任务的项目部署在单台测试环境上,完全没问题。生产上是两台集群服务器,项目部署上去发现定时任务的模块同时在两台机器上各执行了一遍,这将会导致其他意外的发生。

解决方案----redis分布式锁

使用redis分布式锁,为定时任务唯一指定的key加锁,并设置锁超时时间。当触发定时任务时,一台服务的任务进入切面,通过setNX(key,value)方法为唯一的key加锁,如果当前key不存在,将放入缓存,并返回true,通过expire(key,second)设置锁超时时间,结束后跳出执行定时任务方法。第二台服务任务进入时,设置锁的时候发现该锁已存在于缓存,并返回false,不跳转到执行定时任务方法。

核心代码

1.分布式锁切面

@Aspect
@Slf4j
@Component
public class CacheLockAspect {
 private static final String LOCK_VALUE = "locked";
 @Autowired
 private RedisConnection connection;
 @Around("execution(* *.*(..)) && @annotation(com.common.annotation.CacheLock)")
 public void cacheLockPoint(ProceedingJoinPoint pjp) {
 Method cacheMethod = null;
 for (Method method : pjp.getTarget().getClass().getMethods()) {
 if (null!=method.getAnnotation(CacheLock.class)){
 cacheMethod = method;
 break;
 }
 }
 try {
 String lockKey = cacheMethod.getAnnotation(CacheLock.class).lockedPrefix();
 long timeOut = cacheMethod.getAnnotation(CacheLock.class).expireTime();
 if(null == lockKey){
 throw new ManagerException(ErrorMsgEnum.LOCK_NAME_EMPTY);
 }
 if (connection.setNX(lockKey.getBytes(),LOCK_VALUE.getBytes())) {
 connection.expire(lockKey.getBytes(),timeOut);
 log.info("method:{}获取锁:{},开始运行!",cacheMethod,lockKey);
 pjp.proceed();
 return;
 }
 log.info("method:{}未获取锁:{},运行失败!",cacheMethod,lockKey);
 } catch (Throwable e) {
 log.error("method:{},运行错误!",cacheMethod,e);
 throw new ManagerException(ErrorMsgEnum.LOCK_JOB_ERROR,e);
 }
 }
}

2.手写方法级注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CacheLock {
 String lockedPrefix() default ""; //redis 锁key的前缀
 long expireTime() default 10; //key在redis里存在的时间,1000S
}

3.定时任务服务

@Slf4j
@Service
public class TimeTaskService {
 /**
 * 执行定时任务
 **/
 @Scheduled(cron = "0 0 1 * * ?")
 @CacheLock(lockedPrefix = "TimeTaskService",expireTime=30)
 public void executeTask() {
 System.out.println("hello world!");
 }
}


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI