需求:要求定时执行接口任务

需求:要求定时执行接口任务
出现问题:集群环境下,定时任务重复执行。

由于服务都是集群部署,定时任务会在各个服务器上重复执行,轻则浪费服务器资源,重则造成数据紊乱。
quartz定时任务提供了集群方式,但还需为其创建数据库表。spring schedule可以实现简单轻量级的定时任务,但无法保证只执行一次。
通过探讨得知,可以使用redis的分布式锁保证spring schedule集群只执行一次。

@Component
@Configuration
@EnableScheduling
public class AutoConvertTask {
private static final Logger logger = LoggerFactory.getLogger(AutoConvertTask.class);
@Autowired
private RedisTemplate redisTemplate;
private static final String LOCK = "task-job-lock";
private static final String KEY = "tasklock";
@Scheduled(cron = "0 0 0 * * ? ")
public void autoConvertJob() {
boolean lock = false;
try {
lock = redisTemplate.opsForValue().setIfAbsent(KEY, LOCK);
logger.info("是否获取到锁:" + lock);
if (lock) {
List historyList = historyService.findTenDaysAgoUntreated();
for (GameHistory history : historyList) {
update(history);
}
} else {
logger.info("没有获取到锁,不执行任务!");
return;
}
} finally {
if (lock) {
redisTemplate.delete(KEY);
logger.info("任务结束,释放锁!");
} else {
logger.info("没有获取到锁,无需释放锁!");
}
}
}
}

redis分布式锁是通过setnx命令实现的。该命令的作用是,当往redis中存入一个值时,会先判断该值对应的key是否存在,如果存在则返回0,如果不存在,则将该值存入redis并返回1。根据这个特性,我们在程序中,每次都调用setIfAbsent(该方法是setnx命令的实现)方法,来模拟是否获取到锁,如果返回true,则说明该key值不存在,表示获取到锁;如果返回false,则说明该key值存在,已经有程序在使用这个key值了,从而实现了类似加锁的功能
总结:然后按照这段代码提示获取锁,当多个项目同时获取redis分布式锁,你用redis单线程的特性,所以当有一台服务器获取到锁的时候,其他的服务器就无法获取,则可以避免集群,分布式环境下重复执行的问题。

posted @   三号小玩家  阅读(168)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
Title
三号小玩家的 Mail: 17612457115@163.com, 联系QQ: 1359720840 微信: QQ1359720840

喜欢请打赏

扫描二维码打赏

支付宝打赏

点击右上角即可分享
微信分享提示