μ€‘λ³΅λ˜λŠ” μŠ€μΌ€μ€„λ§ λΆ„μ‚°λ½μœΌλ‘œ ν•˜λ‚˜λ§Œ μ‹€ν–‰ν•˜κΈ°(w.ShedLock)

2025. 1. 16. 15:41Β·πŸ“‚ backend/spring
μ½˜μ„œνŠΈ λŒ€κΈ°μ—΄ μ„œλΉ„μŠ€λ₯Ό κ°œλ°œν•˜λ©΄μ„œ 토큰을 만료 μŠ€μΌ€μ€„λ§μ„ μž‘μ—…ν•˜λ©΄μ„œ κ³ λ―Όν–ˆλ˜ λ‚΄μš©μ΄λ‹€. 
같은 μ‹œκ°„μ— λΆ„μ‚° ν™˜κ²½μ—μ„œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„œλ²„λ“€μ˜ μŠ€μΌ€μ€„λ§ 쀑볡 싀행을 λ°©μ§€ν•˜κΈ° μœ„ν•΄ shed lock 을 μ μš©ν–ˆλ‹€.
처음 μ μš©ν•΄λ³Έ κ°œλ…μ— κ΄€ν•΄ μ •λ¦¬ν•˜κΈ° μœ„ν•΄ μž‘μ„±ν•œ 글이닀.

 

 

GitHub - pbg0205/concert

Contribute to pbg0205/concert development by creating an account on GitHub.

github.com

 

 

[1] ShedLock?

ShedLock은 λΆ„μ‚° μ‹œμŠ€ν…œμ—μ„œ μŠ€μΌ€μ€„λŸ¬ μž‘μ—…(Scheduled Tasks)의 쀑볡 μ‹€ν–‰ λ°©μ§€λ₯Ό μœ„ν•΄ μ‚¬μš©λ˜λŠ” λΌμ΄λΈŒλŸ¬λ¦¬μ΄λ‹€. μ—¬λŸ¬ μΈμŠ€ν„΄μŠ€μ—μ„œ μ‹€ν–‰λ˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ λ™μΌν•œ μŠ€μΌ€μ€„λŸ¬ μž‘μ—…μ„ λ™μ‹œμ— μ‹€ν–‰ν•˜μ§€ μ•Šλ„λ‘ 락(Lock)을 μ‚¬μš©ν•˜μ—¬ μ œμ–΄ν•œλ‹€.

  • λΆ„μ‚° ν™˜κ²½ 지원 : ShedLock 은 μ—¬λŸ¬ μ„œλ²„ μΈμŠ€ν„΄μŠ€μ—μ„œ ν•˜λ‚˜μ˜ μŠ€μΌ€μ€„λŸ¬ μž‘μ—…μ— κ΄€ν•œ 싀행을 보μž₯ν•œλ‹€.
  • λ‹€μ–‘ν•œ μŠ€ν† λ¦¬μ§€ 제곡 : λ°μ΄ν„°λ² μ΄μŠ€(MySQL, PostgreSQL λ“±) Redis, DynamoDB λ“±μ˜ λ‹€μ–‘ν•œ μ €μž₯μ†Œλ₯Ό 락 μ €μž₯μ†Œλ‘œ μ‚¬μš©ν•˜κ³  LockProvider λ₯Ό κ΅¬ν˜„ν•˜μ—¬ λ§žμΆ€ν˜• μ €μž₯μ†Œλ₯Ό μ„€μ •ν•  수 μžˆμ–΄ 높은 ν™•μž₯성을 μ œκ³΅ν•œλ‹€.
  • μžλ™ 만료 락 제곡 : μ§€μ •λœ μ‹œκ°„μ΄ μ§€λ‚˜λ©΄ 락이 μžλ™μ„ ν•΄μ œλ˜λ―€λ‘œ μž‘μ—… 쀑단 문제λ₯Ό λ°©μ§€ν•  수 μžˆλ‹€.

λΆ„μ‚° ν™˜κ²½μ—μ„œ μ—¬λŸ¬ λ…Έλ“œμ˜ ν•˜λ‚˜μ˜ μŠ€μΌ€μ€„λ§λ§Œ λ™μž‘μ‹œν‚€κ³ μž ν•œλ‹€λ©΄ ShedLock 을 μ‚¬μš©ν•˜μž.

 

[2] ShedLock λ₯Ό μ μš©ν•΄λ³΄μž.

ShedLock GitHub μ—μ„œ μ œκ³΅ν•˜λŠ” νŠœν† λ¦¬μ–Όμ— κ΄€ν•΄ μ„€λͺ…이 μž˜λ˜μ–΄ μžˆλ‹€. 이λ₯Ό 기반으둜 ShedLock 을 μ μš©ν•΄λ³΄μž.

 

 

GitHub - lukas-krecan/ShedLock: Distributed lock for your scheduled tasks

Distributed lock for your scheduled tasks. Contribute to lukas-krecan/ShedLock development by creating an account on GitHub.

github.com

 

 

(1) build.gradle

  • ShedLock 은 Spring Boot ν™˜κ²½μ—μ„œ μ‰¬μš΄ μ„€μ •κ³Ό μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€. Spring μ—μ„œ ShedLock 을 μ‚¬μš©ν•˜κ³ μž ν•˜λŠ” 경우, shedlock-spring 을 ν˜Έν™˜ν•˜λŠ” μŠ€ν”„λ§ 버전에 맞게 μ μš©ν•˜λ„λ‘ν•˜μž.
  • ν˜„μž¬ ν”„λ‘œμ νŠΈμ—μ„œλŠ” RDB 에 Lock data λ₯Ό 관리할 μ˜ˆμ •μ΄λ―€λ‘œ shedlock-provider-jdbc-template λ₯Ό μ‚¬μš©ν–ˆλ‹€.
dependencies {
    // Shed lock
    implementation 'net.javacrumbs.shedlock:shedlock-provider-jdbc-template:6.2.0'
    implementation 'net.javacrumbs.shedlock:shedlock-spring:6.2.0'
}

 

(2) shedlock schema μΆ”κ°€ν•˜κΈ°

shedlock data λ₯Ό κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄μ„œ λ³„λ„μ˜ ν…Œμ΄λΈ” 선언이 ν•„μš”ν•˜λ‹€. ν…Œμ΄λΈ”μ— κ΄€ν•œ μ •λ³΄λŠ” shedlock GitHub μ—μ„œ μ œκ³΅ν•˜κ³  μžˆμœΌλ‹ˆ μ°Έκ³ ν•˜λ„λ‘ ν•˜μž. (RDB μ—μ„œλŠ” Named Lock 으둜 λ™μž‘ν•˜λŠ” 것 κ°™λ‹€.)

# MySQL, MariaDB
CREATE TABLE shedlock(
   name VARCHAR(64) NOT NULL,
   lock_until TIMESTAMP(3) NOT NULL,
   locked_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
   locked_by VARCHAR(255) NOT NULL,
   PRIMARY KEY (name));

 

(3) LockProvider μΆ”κ°€ν•˜κΈ°

  1. ShedLock 을 ν™œμ„±ν™”ν•˜κΈ° μœ„ν•΄μ„œλŠ” @EnableSchedulerLock 을 μ„ μ–Έν•΄μ•Ό ν•œλ‹€.
    • @EnableSchedulerLock 은 defaultLockAtMostFor μ˜΅μ…˜μ„ μ„€μ •ν•΄μ•Ό ν•œλ‹€.
    • 락의 μ΅œλŒ€ 점유 μ‹œκ°„μ„ μ„€μ •ν•˜λŠ” μ˜΅μ…˜μ΄λ‹ˆ μ„œλΉ„μŠ€ ν™˜κ²½μ— 맞게 μ„€μ •ν•˜λ©΄ 될 것 κ°™λ‹€.
  2. Lock data λ₯Ό κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄μ„œλŠ” LockProvicer λ₯Ό μ„€μ •ν•΄μ•Ό ν•œλ‹€.
    • ν˜„μž¬λŠ” RDB λ₯Ό 기반으둜 μ‚¬μš©ν•  μ˜ˆμ •μ΄λ―€λ‘œ JdbcTemplateLockProvicer λ₯Ό μ μš©ν•œλ‹€.

 

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "10m")
public class ScheduleConfig {

	@Bean
	public LockProvider lockProvider(final DataSource dataSource) {
		return new JdbcTemplateLockProvider(dataSource, "shedlock"); // datasource + table 이름
	}
}

 

(3) ShedLock μ μš©ν•˜κΈ°

  1. μ‹€ν–‰ν•  μŠ€μΌ€μ€„λ§μ— @SchedulerLock μ„ μ–Έν•œλ‹€.
    • name : 락의 key name μ„ μ„€μ •ν•˜λŠ” μ˜΅μ…˜μ΄λ‹€.
    • lockAtLeastFor : 락을 μ μœ ν•  μ΅œμ†Œ μ‹œκ°„μ„ μ„€μ •ν•˜λŠ” μ˜΅μ…˜μ΄λ‹€.
    • lockAtMostFor : 락을 μ μœ ν•  μ΅œλŒ€ μ‹œκ°„μ„ μ„€μ •ν•˜λŠ” μ˜΅μ…˜μ΄λ‹€. μ΅œλŒ€ μ‹œκ°„μ„ μ΄ˆκ³Όν•˜λŠ” 경우 μžλ™μœΌλ‘œ 락을 ν•΄μ œν•œλ‹€.

(μ‹œκ°„μ— κ΄€λ ¨λœ 섀정은 duration+unit / duration in ms / ISO-8601 을 μ§€μ›ν•˜λ―€λ‘œ μžμ„Έν•œ λ‚΄μš©μ„ ν•΄λ‹Ή 링크λ₯Ό μ°Έκ³ ν•˜μž.)

 

@Scheduler
@RequiredArgsConstructor
public class TokenScheduler {

	private final TokenSchedulerUseCase tokenSchedulerUseCase;

	@SchedulerLog
	@Scheduled(fixedRateString = "${queue.processing.rate}", timeUnit = TimeUnit.SECONDS)
	@SchedulerLock(name = "tokenActiveScheduler", lockAtLeastFor = "PT5S", lockAtMostFor = "PT8S")
	public Integer tokenActiveScheduler() {
		return tokenSchedulerUseCase.updateToProcessing(LocalDateTime.now());
	}
}

 

(4) ShedLock 적용 ν™•μΈν•˜κΈ°

local ν™˜κ²½μ—μ„œ μ •μƒμ μœΌλ‘œ μŠ€μΌ€μ€„λ§μ˜ 단일 싀행을 ν…ŒμŠ€νŠΈν•˜κΈ° μœ„ν•΄ program argument(--server.port) 을 μ‚¬μš©ν•΄ 두 개의

application 을 μ‹€ν–‰ν•΄ 단일 μŠ€μΌ€μ€„λ§μ„ 확인해볼 수 μžˆμ—ˆλ‹€.

java -jar build/libs/concert-0.0.1-SNAPSHOT.jar --server.port=8080
java -jar build/libs/concert-0.0.1-SNAPSHOT.jar --server.port=8081

 

port 8080 단일 μŠ€μΌ€μ€„λ§μ„ 보μž₯ν•œλ‹€.

 

 

μ°Έκ³ 

lock data λŠ” key name λ‹Ή ν•˜λ‚˜μ˜ 둜우λ₯Ό κ΄€λ¦¬ν•œλ‹€.

λ§Œμ•½ ν•΄λ‹Ή ν‚€ μ΄λ¦„μ˜ shedlock 이 ν•΄μ œλ˜κ³  잠금이 ν™œμ„±ν™”λ˜λ©΄ ν•΄λ‹Ή 둜우(row)λ₯Ό μ—…λ°μ΄νŠΈν•˜λŠ” λ°©μ‹μœΌλ‘œ λ™μž‘ν•œλ‹€.

 

'πŸ“‚ backend > spring' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

Spring6.1 λΆ€ν„° λ³€κ²½λœ Parameter Name Retention  (0) 2025.03.11
μ»€μŠ€ν…€ μ–΄λ…Έν…Œμ΄μ…˜ 기반 AOP λ₯Ό @Transactional 보닀 λ‚˜μ€‘μ— μ‹€ν–‰μ‹œν‚€κΈ°  (0) 2025.01.27
Spring REST Docs + Swagger UI λ₯Ό ν†΅ν•œ API λ¬Έμ„œν™”  (0) 2024.12.07
비관적 락 vs 낙관적 락(In JPA)  (0) 2024.11.28
MessageSourceAutoConfiguration μ½”λ“œ κ²€ν† ν•˜κΈ°  (0) 2024.11.28
'πŸ“‚ backend/spring' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€
  • Spring6.1 λΆ€ν„° λ³€κ²½λœ Parameter Name Retention
  • μ»€μŠ€ν…€ μ–΄λ…Έν…Œμ΄μ…˜ 기반 AOP λ₯Ό @Transactional 보닀 λ‚˜μ€‘μ— μ‹€ν–‰μ‹œν‚€κΈ°
  • Spring REST Docs + Swagger UI λ₯Ό ν†΅ν•œ API λ¬Έμ„œν™”
  • 비관적 락 vs 낙관적 락(In JPA)
cooper25
cooper25
  • cooper25
    dev cooper
    cooper25
  • 전체
    였늘
    μ–΄μ œ
    • λΆ„λ₯˜ 전체보기 (84)
      • πŸ“‚ backend (34)
        • spring (19)
        • architecture (10)
        • test (5)
      • πŸ“‚ computer-science (5)
      • πŸ“‚ programming-language (12)
        • java (12)
      • πŸ“‚ infra (9)
        • mysql (4)
        • redis (2)
        • message-queue (3)
      • πŸ“‚ cloud (2)
        • aws (2)
      • πŸ“‚ frontend (1)
        • react (0)
      • πŸ“‚ education & lecture (16)
        • 인프라 곡방 (11)
        • ν•­ν”Œ λ°±μ—”λ“œ 7κΈ° (5)
      • πŸ“‚ ai (1)
        • claude (1)
      • πŸ“‚ etc (2)
        • 회고 (1)
        • 컨퍼런슀 (1)
  • λΈ”λ‘œκ·Έ 메뉴

    • ν™ˆ
    • νƒœκ·Έ
    • λ°©λͺ…둝
  • 링크

  • 곡지사항

  • 인기 κΈ€

  • νƒœκ·Έ

    ν•­ν•΄ν”ŒλŸ¬μŠ€
    react
    nGrinder
    spring-batch
    AWS
    가상 λ©΄μ ‘ μ‚¬λ‘€λ‘œ λ°°μš°λŠ” λŒ€κ·œλͺ¨ 섀계
    UUID
    Redisson
    spring camp 2025
    회고
    spring AOP
    JPA
    인프라곡방
    mysql
    데이터 쀑심 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 섀계
    gof
    μŠ€ν”„λ§μΊ ν”„ ν›„κΈ°
    λ™μ‹œμ„±
    spring
    kafka
  • 졜근 λŒ“κΈ€

  • 졜근 κΈ€

  • hELLOΒ· Designed Byμ •μƒμš°.v4.10.6
cooper25
μ€‘λ³΅λ˜λŠ” μŠ€μΌ€μ€„λ§ λΆ„μ‚°λ½μœΌλ‘œ ν•˜λ‚˜λ§Œ μ‹€ν–‰ν•˜κΈ°(w.ShedLock)
μƒλ‹¨μœΌλ‘œ

ν‹°μŠ€ν† λ¦¬νˆ΄λ°”