一种基于Redisson实现简单的分布式定时任务执行方案
一般在springcloud下单机执行定时任务的代码@EnableSchedulingpublic class TestTask {@Scheduled(cron = "0 * * * * ?")public void test() {System.out.println("say hello");}}但因为微服务下一般是多实例部署,会导致定时任务多个实例同时执行的情况。通过对EnableSche
·
一般在springcloud下单机执行定时任务的代码
@EnableScheduling
public class TestTask {
@Scheduled(cron = "0 * * * * ?")
public void test() {
System.out.println("say hello");
}
}
但因为微服务下一般是多实例部署,会导致定时任务多个实例同时执行的情况。
通过对EnableScheduling进行分析,在调用定时方法时会把Method封装成Runnable执行,并且createRunnable可以重写。
因此,只要在Runnable运行时加分布式锁,保证只有一个实例可以获取到锁并执行任务。
@Slf4j
@Configuration
public class SchedulingConfig {
@Autowired
private RedissonClient redissonClient;
@Bean
public ScheduledTaskRegistry scheduledTaskRegistry() {
return new ScheduledTaskRegistry(redissonClient);
}
public static class ScheduledTaskRegistry extends ScheduledAnnotationBeanPostProcessor {
private RedissonClient redissonClient;
public ScheduledTaskRegistry(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
public ScheduledTaskRegistry(ScheduledTaskRegistrar registrar, RedissonClient redissonClient) {
super(registrar);
this.redissonClient = redissonClient;
}
@Override
protected Runnable createRunnable(Object target, Method method) {
String redisKey = RedisKeyUtil.getKey("stask", method.getDeclaringClass().getName() + "." + method.getName());
RLock lock = redissonClient.getLock(redisKey);
Runnable runnable = super.createRunnable(target, method);
return () -> {
if (!lock.tryLock()) {
log.info("运行中: {}", redisKey);
return;
}
log.info("运行: {}", redisKey);
try {
runnable.run();
} finally {
lock.unlock();
}
};
}
}
}
延伸
也可以通过redis分布式锁实现简单的选举leader功能。
更多推荐
已为社区贡献3条内容
所有评论(0)