✅用@Scheduled执行定时任务,如何避免集群的并发问题
典型回答
在 Spring Boot 项目中,@Scheduled 默认在每个实例上都会执行一次任务。如果你的应用部署在集群环境下,所有节点都会执行 @Scheduled 任务,可能导致并发问题。
那么如何解决呢?
他山之石,可以攻玉,先看看xxl-job是咋解决的:
他是基于数据库的悲观锁,多个实例执行的时候,大家一起抢锁,谁抢到了谁执行。
所以,我们也可以用**悲观锁**的思想。
不管使用xxl-job这种select for update的悲观锁,还是基于Redis、Zookeeper来实现分布式锁,都是同样的思想,就是谁抢到锁,谁执行。
几种分布式锁实现方式如下:
但是需要注意,这里最好用非阻塞锁,抢锁失败就直接返回失败,而不是要一直等。那么就可以用redis的tryLock代替lock。
除了加锁之外,还可以用另外一种方案,那就是**选主**
大家不妨想一下,其实是加分布式锁,谁抢到谁执行,这其实就是一种选主,大家一起选择一个master,谁是master谁执行。
那么,就可以用zookeeper,它能实现master选举的能力,任务执行的时候去选主,如果选举成功,则给他执行,否则就不执行。
除了以上方案外,再追问的话,就只能废弃到Scheduling Task这种用法了,用XXL-JOB、 Quartz 等框架代替。