이번에는 저번 구글 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초의 지연이 있습니다.