반응형

들어가며

설명

  • 같은 작업을 수행하는 스케줄러가 각각 다른 서버 인스턴스에서 실행되고 있을 때 중복해서 실행할 필요 없이 한 인스턴스에서만 실행해야할 경우가 있을 수 있다.
  • 이에 대한 처리를 위해 한 인스턴스의 스케줄이 실행될 때 다른 인스턴스의 스케줄을 실행하지 못하도록 락을 걸어 처리하는 것을 Scheduler Lock이라고 한다.
  • 아래는 ShedLock을 활용해 Scheduler Lock 처리를 하는 방법을 소개한다.

ShedLock(with MySQL)

테이블 생성

DROP TABLE IF EXISTS shedlock;
CREATE TABLE shedlock
(
    name       VARCHAR(64),
    lock_until TIMESTAMP(3) NULL,
    locked_at  TIMESTAMP(3) NULL,
    locked_by  VARCHAR(255),
    PRIMARY KEY (name)
);

dependencies

dependencies {
    ...
    implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
    implementation 'mysql:mysql-connector-java'
    implementation 'net.javacrumbs.shedlock:shedlock-spring:4.29.0'
    implementation 'net.javacrumbs.shedlock:shedlock-provider-jdbc-template:4.29.0'
}

application.properties

spring.datasource.url=jdbc:mysql://localhost:13306/test
spring.datasource.username=ubuntu
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

SchedulerConfig

@Configuration
public class SchedulerConfig {
    @Bean
    public LockProvider lockProvider(DataSource dataSource) {
        return new JdbcTemplateLockProvider(dataSource);
    }
}

MyScheduler

@Slf4j
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT1M")
@Component
public class MyScheduler {
    @Scheduled(cron = "0/10 * * * * *") // 0초부터 10초마다 실행
    @SchedulerLock(
        name = "scheduler_lock", // 스케줄러 락 이름 지정. (이름이 동일한 스케줄러일 경우, 락의 대상이 된다.)
        lockAtLeastFor = "PT9S", // 락을 유지하는 시간을 설정한다. (9초로 설정했는데, 스케줄러 주기보다 약간 짧게 지정하는 것이 좋다.)
        lockAtMostFor = "PT9S" // 보통 스케줄러가 잘 동작하여 잘 종료된 경우 잠금을 바로 해제하게 되는데, 스케줄러 오류가 발생하면 잠금이 해제되지 않는다. 이런 경우 잠금을 유지하는 시간을 설정한다.
    )
    public void scheduler1() {
        log.info("1번 스케줄러");
    }

    @Scheduled(cron = "0/10 * * * * *")
    @SchedulerLock(
        name = "scheduler_lock",
        lockAtLeastFor = "PT9S",
        lockAtMostFor = "PT9S"
    )
    public void scheduler2() {
        log.info("2번 스케줄러");
    }
}

ShedLock(with Redis)

dependencies

dependencies {
    ...
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
    implementation 'net.javacrumbs.shedlock:shedlock-spring:4.29.0'
    implementation 'net.javacrumbs.shedlock:shedlock-provider-redis-spring:4.29.0'
}

application.properties

spring.redis.host=localhost
spring.redis.port=6379

SchedulerConfig

@Configuration
public class SchedulerConfig {
    @Bean
    public LockProvider lockProvider(RedisConnectionFactory connectionFactory) {
        return new RedisLockProvider(connectionFactory);
    }
}

MyScheduler

  • 위 과정의 MyScheduler와 동일

참고

반응형

'Development > Spring' 카테고리의 다른 글

[Spring] SpEL  (0) 2023.08.09
[Spring] actuator  (0) 2021.11.27
[Spring] Replication  (0) 2021.11.15
[Spring] @ConfigurationProperties  (0) 2021.08.02
[Spring] @Value  (0) 2021.08.02

+ Recent posts