Scheduled Job多实例下只跑一台实例设计

        Java 代码开发过程中,常常需要跑一些定时任务,而部署的时候为了提供高可用服务,往往部署在启多台实例。这就会引发一个问题,每台实例上的scheduled job都会同时运行,这种情况下可以加实例锁,保证同一时刻只会有一台实例会跑scheduled job.当然,这个问题也可继续做延伸: 做分布式部署的时候,如何保证线程安全?感兴趣的可以在评论区,把日常用的方案写出来,欢迎大家多多交流。

        本文方案是使用锁机制,由于定时任务是多台实例在同一时间开始执行,可以采用锁机制:每台实例在跑之前,先去获取锁,成功获取锁的,开始执行定时任务,获取不到的,放弃执行。lockid 存储在mongodb中,当然也可以存储在redis中。

第一步,创建一个model,用于保存lockid.

@Data
@Document(collection = "scheduled_lock")
public class ScheduledLock{
@Id
  private String id;

  @CreatedDate
  @Field("created_date")
  @JsonIgnore
  @Indexed(expireAfterSeconds = 3600) // = 3600 seconds
  private ZonedDateTime createdDate = ZonedDateTime.now();
}

expireAfterSeconds 这个属性用来设置TTL.

第二步,实现lock, unlock方法。

public T lock(T lock) {
    log.debug("Request to define lock : [{}]", lock);
    return mongoLockRepository.insert(lock);
}

public void unlock(T lock) {
    log.debug("Request to release lock : [{}]", lock);
    mongoLockRepository.delete(lock.getId());
}

第三步,scheduled job跑之前先获取锁,获取不到的就不运行。

@Scheduled
public void  scheduledJob() {
  log.info("begin to run sheduled job ....");
  ScheduledLock scheduledLock = new ScheduledLock();
  scheduledLock.setId("scheduled_job");
  try {
    // lock the current instance
    scheduledLockService.lock(scheduledLock);
    try {
      log.info("I get the lock and run schuduled job ...");
      handleData();
    } catch (Exception e) {
      log.error("handle data error", e);
    } finally {
      log.info("Finished to process.");
      // release lock
      scheduledLockService.unlock(scheduledLock);
    }
  } catch (DuplicateKeyException exception) {
    // don't get the lock
    log.warn("run scheduled job can't get the lock id");
  }
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值