Adventure Time - Finn 3

새소식

운영체제

DeadLock과 Redis 대기열 사용하기 - (1)

  • -

이번에는 저번 구글 I/O Extended 2023 백엔드에서 들었던 GDG Incheon 백엔드 양일표 개발자님께서 강연해주셨던 DeadLock과

Redis 대기열 사용하기에서 새로 알게 된 내용과 깨달은 점을 정리해보려고합니다.

 

🧐 DeadLock

 

우선 DeadLock이란 둘 이상의 프로세스가 다른 프로세스가 점유하고 있는 자원을 서로 기다릴 때 무한 대기에 빠지는 상황을 일컫습니다.

 

DeadLock

 

 

 

이 때 DeadLock에 대한 해결법이 여러가지가 있는데 강연 중 소개해주신 해결법들은 트랜잭션의 크기, 방향, Lock, 격리 수준, 쿼리 튜닝, @Retryable 등과 같은 요소들을 고려하는 방법입니다.

 

 

1. 트랜잭션 크기 조절

  • 트랜잭션 분할: 큰 트랜잭션을 작은 단위로 분할하여 실행하면, 더 적은 자원을 점유하므로 교착 상태 발생 가능성이 줄어듭니다.
  • 트랜잭션 우선순위 설정: 중요한 작업에 우선순위를 부여하여, 해당 작업을 먼저 처리하도록 할 수 있습니다.

 

2. 트랜잭션 방향 조절

  • 단방향 대기: 트랜잭션들 사이에 대기 관계를 단방향으로 만들어줍니다. 즉, A가 B를 대기하는 경우 B는 A를 대기하지 않도록 합니다.
  • 자원 할당 순서 조정: 특정한 자원들을 동일한 순서로 요청하도록 규칙을 정해줍니다. 이렇게 하면 모든 트랜잭션들이 같은 자원 요청 순서를 따르며 교착 상태의 가능성이 줄어듭니다.

 

3. 적절한 Lock 사용

  • 공유 Lock (Shared Lock)과 배타적 Lock (Exclusive Lock)의 조절: 트랜잭션이 자원을 사용할 때, 공유 Lock과 배타적 Lock을 적절하게 사용하여 다른 트랜잭션들과 충돌을 최소화합니다. 자원을 읽을 때는 공유 Lock을, 자원을 변경할 때는 배타적 Lock을 사용합니다.

 

4. 격리 수준 설정

  • 격리 수준 설정: 데이터베이스의 격리 수준을 조절하여 트랜잭션 간 충돌을 제어할 수 있습니다. 낮은 격리 수준은 읽기 충돌 가능성이 줄어들지만, 높은 격리 수준은 데드락 가능성이 높아질 수 있습니다. 애플리케이션의 요구에 맞는 적절한 격리 수준을 선택합니다.

 

5. 쿼리 튜닝

  • 인덱스 최적화: 자주 사용되는 컬럼에 인덱스를 생성하여 쿼리의 실행 속도를 향상시키고 Lock의 범위를 줄입니다.
  • 조건 최적화: 쿼리의 조건을 최적화하여 필요한 데이터만 추출하도록 하여 자원 점유를 최소화합니다.
  • 조인 최적화: 비효율적인 조인을 개선하여 쿼리의 실행 계획을 최적화합니다.
  • 트랜잭션 범위 축소: 트랜잭션 범위를 최소화하여 자원 점유 기간을 단축시키고 데드락 가능성을 줄입니다.

 

6. @Retryable Annotation 사용

  • @Retryable 애노테이션은 Spring Framework에서 제공하는 기능으로, 특정 예외가 발생할 경우 메소드를 자동으로 재시도하도록 도와줍니다. 이를 활용하여 데드락이 발생하면 특정 작업을 자동으로 재시도하도록 만들 수 있습니다. 이때 주의해야 할 점은 반복적인 재시도가 무한히 이어지지 않도록 적절한 재시도 횟수나 제한 조건을 설정해야 합니다.

 

 

예시 코드

import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

@Service
public class MyService {
    
    @Retryable(
        value = {DeadlockDetectedException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000)
    )
    public void performDatabaseOperation() {
        // 데이터베이스 작업 수행
        // 데드락 발생 시 DeadlockDetectedException 예외가 던져짐
    }
}

위의 예시에서는 performDatabaseOperation 메소드가 데드락을 감지하면 DeadlockDetectedException 예외를 던지도록 설정하고, @Retryable 애노테이션을 통해 해당 예외가 발생하면 최대 3번의 재시도를 시도하며 각 재시도 사이에는 1초의 지연이 있습니다.

 

 

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.