乱写了一点代码, 原型是微服务分布式部署中,某个定时任务只需要某个节点定时跑一次就可以了,不需要所有节点都跑, 而Springboot的定时任务设置是只针对当前节点的,所以就需要加入手段去防止一下,于是有了下面的代码:
1. 自定义Annotation注解,标识了该注解的定时任务既只能由某一个节点执行
2. AOP识别标识了自定义注解的定时任务,完成执行方法前的加锁和竞争锁的功能,分布式锁由redis实现。
3. 定时任务执行方法体
【aop编程方式可以实现分布式锁方便在其他有类似功能(分布式锁)的地方使用】
直接上代码:
1. 自定义注解
import java.lang.annotation.*;
@Target(ElementType.METHOD) // 可以在方法上注解 @Retention(RetentionPolicy.RUNTIME) // 运行时生效
@Documented
public @interface ScheduleLock {
String key();
int timeout() default 10;
}
2. AOP, 识别注解,并实现加分布式锁功能
@Component
@Aspect
public class RedisLockAspect {
@Autowired
StringRedisTemplate strRedis;
@Pointcut(value = "@annotation(org.wyq.annotation.ScheduleLock)")
public void scheduleLock() { }
@Around(value = "scheduleLock() && @annotation(lock)")
public Object scheduleLockFunc(ProceedingJoinPoint point, ScheduleLock lock) throws Throwable {
String key = lock.key();
Boolean aBoolean = strRedis.opsForValue().setIfAbsent(key, UUID.randomUUID().toString(), lock.timeout(), TimeUnit.SECONDS);
if (!aBoolean) {
System.out.println("获取失败");
return null;
}
Object proceed = point.proceed();
return proceed;
}
}
3. 定时任务,锁会在60秒后自动失效,既定时任务执行只保护60秒,一般的服务器节点集群都会有时钟同步
@Configuration
@EnableScheduling
public class ScheduledConfig {
@Scheduled(cron = "0 38 1 * * ?")
@ScheduleLock(key="scheduleTest", timeout = 60)
public void scheduleLockFunc(){
System.out.println("方法体");
}
}
以上功能需要在pom中引入的包:
测试,端口不同启动3个节点,到点执行结果:
01节点获取锁失败
02节点获取锁失败
03节点获取锁成功,执行方法体
本文介绍了如何在SpringBoot的微服务分布式部署中,确保某个定时任务只由一个节点执行。通过自定义 Annotation、AOP 和 Redis 分布式锁,实现了节点间的任务竞争和锁机制。在代码示例中,展示了如何定义注解、创建AOP切面以及配置定时任务,确保锁在60秒后自动失效,以适应集群环境的时间同步需求。




1278

被折叠的 条评论
为什么被折叠?



