springboot部署多个相同服务deploy,当服务中有定时器时,一旦定时器触发时服务会同时执行,从而产生并发问题。解决方案:
1.在定时器类添加@Profile 注解 指定实例执行定时器。
@Component
@Configuration
@EnableScheduling // 1.开启定时任务
@Profile("deploy01")
public class ScheduleTaskService {
....
}
它操作简单,灵活。只需要添加@Profile注解,但它的局限性也很明显,只有指定服务为deploy01时才会加载定时器处理类,一旦deploy01 挂掉或者未启动就无法执行。所以并不能达到高可用。
2.利用redis 缓存机制
@Scheduled(cron = "0 0 0/1 * * ? ") //每1小时执行一次
public void insertPriRecoverCall() throws InterruptedException {
String deployKey="deployName";
redisService.set(deployKey,deployId,1,TimeUnit.HOURS);
Object o = redisService.get(deployKey);
if (o!=null){
String deployName = o.toString();
if (deployId.equals(deployName)){
logger.info(deployName+" is running .....");
业务代码
}
}
}
先获取服务实例Id,缓存到redis中。redis 是key-value 键值对的缓存机制。在相同key下只会保留一个deployId ,再取出缓存中deployId和服务实例id 比较。相同就继续执行业务代码,不同则直接过滤。这样既可以防止并发问题,又可以实现高可用。