redis主从集群搭建eclipse_基于redis的spring task集群配置

项目从单节点环境变为集群环境,这个时候要确保项目中的定时任务同一时刻只能在集群中的其中一个服务器中运行,但又不能写死在哪一台服务器上运行,怎样才能实现这样的需求?

思路:

可以做一个切面,扫描定时任务,在任务开始之前使用redis缓存判断任务是否启动,由于Redis是单线程按顺序执行命令,可以在每个定时任务执行前,使用setnx方法判断是否可以添加值,如果添加成功,说明这个定时任务没有被执行,设置key的过期时间并让定时任务执行,如果不可以添加值,说明该定时任务已经在其他服务器上跑了,方法之间返回。Key的过期时间要大于集群中方法执行setnx的总和,不大于定时任务的时间间隔。

1.定义一个自定义注解,用于配置定时任务的key,到期时间,存储库等信息

packagecom.study.task;importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;

@Target({ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documentedpublic @interfaceTaskRedisConfig {/**redis存储对应的key*/String key()default "";/**key对应的value值*/String value()default "1";/**选用第一个redis库存储该key*/String index()default "0";/**该key的过期时间*/String timeout()default "30";/**是否允许多节点并发运行*/

boolean isConcurrent() default false;

}

2.定义一个切面,扫描定时任务,在定时任务执行之前用redis的setnx做判断

packagecom.study.aop;importjava.lang.reflect.Method;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.annotation.Pointcut;importorg.aspectj.lang.reflect.MethodSignature;importorg.springframework.context.annotation.EnableAspectJAutoProxy;importorg.springframework.stereotype.Component;importcom.study.task.TaskRedisConfig;importcom.study.util.RedisUtil;importredis.clients.jedis.Jedis;

@Aspect

@Component

@EnableAspectJAutoProxypublic classTaskAop {

@Pointcut("@annotation(org.springframework.scheduling.annotation.Scheduled)")public voidpointcut(){}/*@Before("pointcut()")

public void taskBefore(JoinPoint joinPoint) {

String methodName = joinPoint.getSignature().getName();

System.out.println(methodName);

Method method = (Method)joinPoint.getThis();

//Method method = (Method)joinPoint.getTarget();

if(method.isAnnotationPresent(TaskRedisConfig.class)) {

System.out.println("aaaaaaaaaa---------");

}

}*/@Around("pointcut()")public void taskBefore(ProceedingJoinPoint joinPoint) throwsThrowable {

String methodName=joinPoint.getSignature().getName();

System.out.println(methodName);

MethodSignature methodSignature=(MethodSignature)joinPoint.getSignature();

Method method=methodSignature.getMethod();if(method.isAnnotationPresent(TaskRedisConfig.class)) {

TaskRedisConfig tc= method.getAnnotation(TaskRedisConfig.class);

String index=tc.index();

Jedis jedis=RedisUtil.getJedis();

jedis.select(Integer.parseInt(index));

String key=tc.key();

String value=tc.value();

String timeout=tc.timeout();boolean isConcurrent =tc.isConcurrent();if(!isConcurrent) {//设置成功,返回 1 。 设置失败,返回 0 。

long result =jedis.setnx(key, value);if(result==1) {long exresult =jedis.expire(key, Integer.parseInt(timeout));

joinPoint.proceed();

jedis.close();

}else{return;

}

}

}

}

}

3.写一个定时任务类,用于测试

packagecom.study.task;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;

@Servicepublic classSimpleTask {

@Scheduled(cron= "0/10 * * * * ?")

@TaskRedisConfig(key="simpleTask:methodOne",timeout="9",index="2")

@Transactionalpublic voidmethodOne() {

System.out.println("methodOne----,时间:" + System.currentTimeMillis()/1000);

}

@Scheduled(cron= "0/20 * * * * ?")

@TaskRedisConfig(key="simpleTask:methodTwo",timeout="18",index="2")public voidmethodTwo() {

System.out.println("methodTwo----,时间:" + System.currentTimeMillis()/1000);

}

}

可以向项目放到两个工作空间下,用两个eclipse进行分别启动该两个项目,查看结果

原文:https://www.cnblogs.com/sjcq/p/8973528.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值