본문 바로가기
프로젝트

파이널 프로젝트_ShedLock을 이용한 스케쥴 중복실행 방지

by 유서담 2024. 5. 9.

참고한 블로그

https://blog.naver.com/hohomax/223380841680

 

Spring 스케쥴 중복실행 방지하기! (ShedLock)

Spring 스케쥴 중복실행 방지하기! (ShedLock) 요즘은 단일서버 구성을 하지않고 트래픽이나 사용량에 ...

blog.naver.com

 


 

내가 담당한 파트에서도 

@Scheduled 을 사용하는 코드가 있다보니 적용해보기로 했다

 

 

ShedLock을 사용하면 좋은점

 

ShedLock은 스케줄된 작업을 관리 및 중복 실행을 방지하는 데 사용된다

 

중복 실행방지 

ShedLock을 사용하면 동일한 스케줄된 작업이 여러 서버에서 중복해서 실행되는 것을 방지할 수 있다

(시스템 리소스의 낭비를 줄이고, 데이터 일관성을 유지하는데 도움이 된다)

 

데이터베이스 락을 통한 안전한 잠금 관리

데이터베이스를 사용하여 잠금 관리하므로 데이터베이스 레벨에서 안전하고 일관된 잠금 메커니즘을 제공한다.

(분산 환경에서 잠금관리를 간편하게 해주며, 트랜잭션 관리와의 호환성을 보장한다)

 

스케줄된 작업의 일관성 유지

스케줄된 작업이 동일한 시간에 한 번만 실행되도록 보장할 수 있다.

(작업의 일관성을 유지하고 시스템의 안정성을 향상시킨다)

 

유연성

ShedLock은 JDBC, MongoDB, Redis 등 다양한 데이터베이스를 지원해서 애플리케이션의 요구사항에 맞게 선택할 수 있다

 

안정성

새로운 인스턴스를 추가하거나 기존 인스턴스를 제거해도, ShedLock이 작업의 중복 실행을 막기 때문에 시스템의 안정적인 운영을 보장한다

 

실행시간 제어

작업의 실행시간을 제어할 수 있다. 예를 들어, 작업이 지정된 시간 동안 실행되지 않도록 할 수 있다.

(예기치 않은 장애로 인해 작업이 오랜 시간동안 실행되지 않는 것을 방지할 수 있다)

 

 

 


 

 

.gradle 파일 의존성 추가

 

 

 

net.javacrumbs.shedlock:shedlock-spring:5.10.0

 

Spring 기반 애플리케이션에서 ShedLock을 사용할 수 있도록 지원한다

 

 

net.javacrumbs.shedlock:shedlock-provider-jdbc-template:5.10.0

 

JDBC Template을 사용하여 데이터베이스를 통해 ShedLock을 구현한다

 

 

 

참고로 프로젝트 설정은

jdk17, Spring Boot 3.2.4, MySQL 을 사용한다

 

jdk, Spring Boot의 버전이 낮다면 아래와 같이 의존성 주입을 해야한다

(jdk11, Spring Boot 2.5.6일때의 예시)

implementation 'net.javacrumbs.shedlock:shedlock-spring:4.44.0'
implementation 'net.javacrumbs.shedlock:shedlock-provider-jdbc-template:4.44.0'

 

 

 

 

application.properties 설정

 

 

 

ShedLock Config 클래스 작성

@Controller
@EnableScheduling
@EnableSchedulerLock(defaultLockAtLeastFor = "30s", defaultLockAtMostFor = "50s")
public class ShedLockConfig {

    @Bean
    public LockProvider lockProvider(DataSource dataSource){
        return new JdbcTemplateLockProvider(
            JdbcTemplateLockProvider.Configuration.builder()
                    .withJdbcTemplate(new JdbcTemplate(dataSource))
                    .usingDbTime()
                    .build()
        );
    }
}

 

@EnableScheduling : Spring의 스케줄링 기능을 활성화

 

@EnalbleSchedulerLock : ShedLock 프레임워크의 스케줄러 잠금을 활성화.

defaultLockAtLeastFor : 기본으로 Lock이 유지되는 최소시간 ( 수행시간이 매우 빠를 때 중복실행이 일어나는 문제를 방지할 수 있다 )

defaultLockAtMostFor : 기본으로 Lock이 유지되는 최대시간 ( 수행시간이 길어지거나, 끝나지 않을 때 다음 순서가 실행되지 않는 문제를 방지할 수 있다 )

 

 

 

 

ShedLock 관련 데이터를 처리하기 위한 테이블 생성

CREATE TABLE shedlock(
    name VARCHAR(64), # job의 name PK로 활용
    lock_until TIMESTAMP(3) NULL, # 2024-03-12T20:31:00.012189300 단위까지 체크 가능하도록 필드 타입 설정
    locked_at TIMESTAMP(3) NULL,
    locked_by VARCHAR(255) NOT NULL, # 작성자 정보
    PRIMARY KEY (name)
)

 

 

 

Service 생성

@Service
public class ScheduleTask {

    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleTask.class);

    //@Scheduled(cron = "0 * * * * ?") // 매분마다 실행
    @SchedulerLock(name = "ScheduledTask_run")
    public void runTask() throws InterruptedException {
        System.out.println("task1: " + LocalDateTime.now());
    }

    //@Scheduled(cron = "0 * * * * ?") // 매분마다 실행
    @SchedulerLock(name = "ScheduledTask_run")
    public void runTask2() throws InterruptedException {
        System.out.println("task2: " + LocalDateTime.now());
    }
}

 

 


 

ShedLock 처리 전

task 1, 2가 중복 실행되는 모습

 

 

 

ShedLock 처리 후

task1만 실행되는 모습

 

 

 

 

 

MySQL에서  shedlock 테이블 조회결과

조회결과