목록으로 돌아가기
낙관적 락(Optimistic Locking)
2025년 12월 20일
1개 태그
optimistic lock
낙관적 락(Optimistic Locking)
낙관적 락은 충돌이 적을 때 사용하는 방식입니다. 비관적 락과 달리 읽기 시 락을 걸지 않고, 저장 시 버전을 확인해 충돌을 감지합니다.
현재 구현 분석
1. Version 필드 추가
@Version @Column("version") var version: Long = 0 - @Version: Spring Data R2DBC가 자동으로 버전 관리 - 읽기 시: 현재 version 값을 함께 조회 - 저장 시: WHERE 절에 version 조건 추가 - 성공 시: version 자동 증가
-
@Version: Spring Data R2DBC가 자동으로 버전 관리
-
읽기 시: 현재 version 값을 함께 조회
-
저장 시: WHERE 절에 version 조건 추가
-
성공 시: version 자동 증가 2. 동작 원리
-
- 저장 시 실행되는 쿼리 (개념적)
UPDATE credit_balances SET balance = 150, version = version + 1, updated_at = NOW() WHERE id = 'xxx' AND version = 1 -- 읽었던 version과 일치해야 함 - 만약 다른 트랜잭션이 먼저 업데이트했다면 -- version이 2로 변경되어 있으므로 WHERE 조건이 실패 -- → 0 rows affected → OptimisticLockingFailureException 발생
다이어그램
시나리오 1: 정상적인 경우 (충돌 없음)
다이어그램 로딩 중...
시나리오 2: 동시성 충돌 발생 및 재시도
다이어그램 로딩 중...
전체 프로세스 플로우
다이어그램 로딩 중...
데이터베이스 상태 변화
다이어그램 로딩 중...
코드에서의 동작
1. Entity에 Version 필드
다이어그램 로딩 중...
- R2DBC가 자동으로 버전 관리
- 저장 시 WHERE 절에 version 조건 추가 2. 재시도 메커니즘
다이어그램 로딩 중...
- Retry.backoff: 지수 백오프 재시도
- filter: OptimisticLockingFailureException만 재시도
- Mono.defer: 재시도마다 최신 잔액 재조회 3. 트랜잭션 원자성
다이어그램 로딩 중...
- 잔액 저장과 거래 내역 저장을 하나의 트랜잭션으로 묶음
- 하나라도 실패하면 전체 롤백
장점과 단점
장점
- 읽기 성능: 읽기 시 락 없음
- 동시성: 여러 읽기 동시 처리 가능
- 데드락 방지: 락 대기 없음
단점
- 충돌 시 재시도 필요: 성능 오버헤드
- 최종 실패 가능: 재시도 한도 초과 시
- 복잡도: 재시도 로직 필요
실제 동작 예시
시나리오: 두 사용자가 동시에 크레딧 차감
다이어그램 로딩 중...
핵심 포인트
- Version 필드: 각 업데이트마다 자동 증가
- WHERE 조건: 저장 시 읽었던 version과 일치해야 성공
- 충돌 감지: version 불일치 시 OptimisticLockingFailureException
- 재시도: 최신 version으로 다시 시도
- 원자성: TransactionalOperator로 잔액+거래 내역을 하나의 트랜잭션으로 처리
댓글 (0)
아직 댓글이 없습니다. 첫 번째 댓글을 작성해보세요!