Programing/Java & Spring

[Spring] Scheduling LockProvider 사용 목적과 사용 시 고려할 사항 정리

세기루민 2023. 3. 21. 08:36
728x90

최근에  업무를 하다가 Scheduling 변경 사항이 존재하여 LockProivder에 대해 알아봤는데 

내가 알아본 내용과 업무 시 고려해야 할 사항에 대해 간략하게 정리를 해보려고 한다. 

 


1. LockProvider 사용 목적 및 의미

LockProvider를 사용하는 목적은 아래와 같다. 

- 스케줄러의 중복 실행 방지 

- 실무에서 하나의 어플리케이션을 이중화 및 N중화를 한 경우가 대부분이다. 서버가 많으면 많을 수록 스케줄러의 Lock은 중요한 사항이 되며 이를 하지 않는 경우 어떤 서버가 배치를 처리해야 할 지 모르기 때문에 중복 실행이 될 수 있고 이는 큰 문제가 될 수 있다.(예를 들어 결제 시스템 새벽 배치인 경우 결제가 여러번 될 수 있다는 의미)

- 따라서 순서와 관계 없이 1개의 서버가 실행하는 동안 Lock을 걸어 다른 서버에서 실행하지 못하도록 막는 역할을 한다고 보면 된다

 

2. 사용 방법 

[아래의 소스코드는 예시로 실제 돌아가는 코드로 작성한 것이 아니라는 점 양해 부탁드립니다.]

1. Table 생성

// Table 생성 
CREATE TABLE SHCEDULING_LOCK_MGNT_TB (
   SCHEDUL_NAME VARCHAR(100), 			// 스케줄러 이름 
   LOCK_UNTIL	TIMESTAMP(3),			// 잠금 기간
   LOCKED_AT	TIMESTAMP(3),			// 잠금 일시
   LOCKED_BY	VARCHAR(50)			// 잠금 위치
)

- LockProvider에 연결할 테이블을 생성합니다. 

- 컬럼명은 자유롭게 만들어도 무관하지만 Column을 연결해줘야 합니다.(withColumnNames)

 

2. Dependency 

<!-- https://mvnrepository.com/artifact/net.javacrumbs.shedlock/shedlock-spring -->
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-spring</artifactId>
    <version>4.33.0</version>
</dependency>
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-jdbc-template</artifactId>
    <version>4.33.0</version>
</dependency>

- shedlock-spring과 shedlock-provider-jdbc-template 2개를 추가해줍니다.(gradle도 동일)

3. Config 파일 생성하기 

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "5m", defaultLockAtLeasterFor = "5m")
public class SchedulingConfiguration {
    @Bean
    public LockProvider lockProvider(DataSource dataSource) {
    	return new JdbcTemplateLockProvider(builder()
            .withTableName("SHCEDULING_LOCK_MGNT_TB")
            .withColumnNames(new JDBCTemplateLockProvider.ColumnNames("SCHEDUL_NAME", "LOCK_UNTIL", "LOCKED_AT", "LOCKED_BY"))
            .withJdbcTemplate(new JdbcTemplate(dataSource))
            .build());    
    }
}

- @EnableScheduling 어노테이션을 이용하여 스케줄러 기능을 활성화 하고 @EnableSchedulerLock 어노테이션을 통해 스케줄러의 잠금 기본 시간을 설정해줍니다.

lockProvider을 선언할 때 Table 이름, 컬럼 이름을 설정하여 스케줄러를 위해 생성한 테이블과 매칭시켜줍니다. 

(이렇게 하지 않아도 상관 없으나 테이블 명과 컬럼 명이 일치하지 않는 경우라면 매칭시켜주는게 좋음)

4. 테스트

@Slf4j
@Component
public Class Scheduler {

    @Scheduled(cron = "0 0 1 * * *")
    @SchedulerLock(name = "SgmoominTest")
    public void DefSchedulerTest(){
    	log.info("스케줄러 테스트입니다.")
        log.info("해당 스케줄러는 새벽 1시에 실행될 것입니다.")
    }
}

- @Scheduled 어노테이션을 이용하여 해당 스케줄이 몇시에 실행 될 것인지 설정해줍니다.(예시에는 새벽 1시)

- @SchedulerLock은 스케줄러 락에 대한 구분값을 설정해주는 어노테이션이라고 보면 되며 이는 설정된 시간에 해당 Lock이 중복 실행되지 않도록 설정해줍니다.

 

3. 기타 고려 사항 

스케줄러 변동(삭제)에 따른 스케줄러 LOCK 테이블 데이터 변경 사항이 존재할 경우 어플리케이션을 재 실행해야 합니다.

(인메모리에 테이블의 정보를 가지고 있기 때문에 테이블에 값만 변경하더라도 바로 적용이 안됨)

 


이번 포스팅에서는 간략하게 Scheduling Lock에 대해 작성해봤습니다. 

다음 포스팅에서는 SchdulingConfigurer에 대해 포스팅 하는 시간을 가져보도록 하겠습니다.

728x90