> ## Content Index
> Fetch the complete content index at: https://www.popit.kr/llms.txt
> Use this file to discover other available public pages before exploring further.

# ShedLock을 이용한 Master - Slave (primary - secondary, leader - follower) 구분 없는 스케줄러 만들기
- URL: https://www.popit.kr/shedlock-master-slave-leader-election/
- Published: 2019-04-25T00:02:44.000Z
- Updated: 2019-04-25T00:06:03.000Z
- Author: sun
- Tags: #소프트웨어, 이중화, #팁, 배치프로그램, ShedLock

스케줄을 처리하는 인스턴스 A와 B가 떠 있을때, 별도의 Master - Slave 구분 없이 둘 중 하나의 인스턴스가 처리하도록 하려면 어떻게 해야 할까요?

![troubleshooting](https://www.popit.kr/content/images/wp/2019/04/troubleshooting-600x225.jpg)

어쩔때는 A 가 돌고, 어쩔때는 B 가 돌고...  
A 가 죽어도 알아서 B 가 돌고 하는 구성을 만들고 싶을때 말이죠.

이런 고민을 하다가 얼마전 발견한 라이브러리 입니다.

[https://github.com/lukas-krecan/ShedLock](https://github.com/lukas-krecan/ShedLock?ref=popit.kr)

일반적인 경우 Quartz 를 사용하거나 Spring 에서 제공하는 스케줄러를 사용해 주기적인 작업을 처리하도록 개발합니다.

그리고, 많은 경우 배치 인스턴스를 만들면 하나만 띄워서 실행을 해요. 그러다가 죽기라도 하면,

- 업무시간에 죽으면 그냥 재시작 하면 되지만
- 집에서 자다가 알림 받고 인스턴스를 다시 띄우거나,
- 애기보다가 알림을 못 받을 수도 있고,
- 술먹고 기절이라도 했다면 몇 시간동안 스케줄된 작업이 돌지 않겠죠.

그래서 나온 것이 바로 ShedLock 입니다.

ShedLock 은

1. 저장할 대상을 선정한 후
2. 데이터 저장소에 테이블 하나 생성해주고
3. Maven Dependency 를 추가해주고
4. Bean 하나 Copy & Paste 하고  
5.스케줄 메소드에 어노테이션 추가만 해주면  
끝납니다.

이렇게 5단계로 진행한다고 해서 복잡해 보일 수도 있는데, 실제로 적용해 보면 아주 간단해요.

사용 가능한 저장소는 다음과 같습니다.

- Mongo
- DynamoDB
- JdbcTemplate
- ZooKeeper (using Curator)
- Redis (using Spring RedisConnectionFactory)
- Redis (using Jedis)
- Hazelcast

그러면 회사에서 주력으로 사용하는 mySql 을 예로 들어 볼게요.

1. 저장할 대상 : mySql

Maven Dependency  

```
<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-jdbc-template</artifactId>
    <version>2.4.0</version>
</dependency>

```

  
테이블 생성  

```
CREATE TABLE shedlock(
    name VARCHAR(64), 
    lock_until TIMESTAMP(3) NULL, 
    locked_at TIMESTAMP(3) NULL, 
    locked_by  VARCHAR(255), 
    PRIMARY KEY (name)
)
```

  
어노테이션 추가 @SchedulerLock 부분 참고  

```
import net.javacrumbs.shedlock.core.SchedulerLock;

...

@Scheduled(...)
@SchedulerLock(name = "scheduledTaskName")
public void scheduledTask() {
   // do something
}
```

Bean 추가  

```
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;

...

@Bean
public LockProvider lockProvider(DataSource dataSource) {
    return new JdbcTemplateLockProvider(dataSource);
}
```

만약 스케줄러가 여러 개라면 scheduledTaskName 값을 다르게 해 주면 됩니다.

이렇게 설정하고 나서 두개의 인스턴스를 띄워 놓으면,  
각각의 인스턴스 중 하나가 2번에서 생성한 테이블에 값 하나를 저장해 놓고 작업을 실행하고, 다른 인스턴스는 테이블에 값이 업데이트 되어 있기 때문에 일을 안하고 잠을 잡니다.

테스트를 해 본 결과 하나만 지속적으로 사용하지는 않고 두개의 인스턴스가 규칙 없이(?) 일을 나누어 실행하는 것을 확인할 수 있었습니다.