@ScedulerLock踩坑

背景:我们需要做一个分布式定时任务,定时给用户发短信,设计思路是用@SchedulerLock做分布式定时任务,任务是从每次从数据库查询1000条用户数据,并异步发送短信,发送完成后在数据库里记录发送信息,@Schedule配置为@Scheduled(cron = “0/5 0/1 10-17 * * ?”),@SchedulerLock配置为 @SchedulerLock(name = SCHEDULE_MODEL_NAME + “ticketRemind”, lockAtLeastFor = “PT5S”, lockAtMostFor = “PT10S”)

问题:我们发现有用户收到两条相同的短信,且间隔时间1s

排查思路:先查看数据库,发现确实有对相同用户发送两条短信的记录,且间隔时间为1s,并且同一批1000个用户,每个用户都发送了两次,随后查询系统日志,发现任务确实如@Scheduled配置每5s执行一次,如果获取不到分布式锁,就在下一个5s执行,查询问题前后的日志,发现在11:03:25的定时任务在11:03:37才处理完,同时在11:03:35又开始了新的定时任务,因此可以推断出,由于我们的lockAtMostFor设置只有10s,因此当任务处理时间超过10s时,该任务处理节点就会放弃分布式锁,其他节点可以获得该分布式锁,由于前一个任务还没有处理完成,数据库里还没有任务完成的记录,因此会导致下一个节点执行相同的任务。

解决办法
1.保证任务不可重复执行
由于我们的业务需要在任务确实处理完成后,才能记录完成信息,不能保证不可重复执行,因此需要想其他办法
2.增大lockAtMostFor 时间
无法百分之百地保证任务不会重复执行,但是能大大降低任务重复执行的概率

思考:如果不设置lockAtMostFor ,知道任务处理完成才释放锁,那么当该节点出现问题时,锁可能就会一直锁住,无法让出锁给其他节点处理,显然不合适,而设置了就可能会出现任务重复执行的问题,不知道@SchedulerLock能不能在超时的时候回滚任务或者跳过该任务

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值