Concurrency issue: 데드락을 제거하며 정합성 유지하기
문제: 운영에서 발생한 데드락 발생과 데이터 불일치
문제 분석: 데드락과 정합성 문제 발생 상황 조사
1. 일기 작성 동시 요청 시 데드락 발생
2. 작성 재촉하기 동시 요청 시 데드락 발생
3. 일기 작성과 작성 재촉하기 동시 요청
데드락 원인 분석
락 획득 시점 분석
일기 작성 요청 진행 순서
작성 재촉하기 요청 진행 순서
API 응답 속도 분석
정리
1차 개선: 트랜잭션 범위 축소와 락 획득 순서 정렬 시도
트랜잭션 범위 축소: FCM 알림 비동기 처리
비동기 처리를 위한 스레드 풀 설정
락 획득 순서 정렬
기존 락 획득 순서
애플리케이션 레벨에서 락 순서 정렬 시도
문제 발견: JPA는 코드 순서대로 쿼리를 실행하지 않는다.
1차 개선의 한계
정리
정합성 원인 분석
Read-Modify-Write와 Check-Then-Act 패턴의 위험성
Read-Modify-Write 패턴
Check-Then-Act 패턴
문제 발생 상황
Lost Update 상황: 일기 작성 커밋 → 재촉하기 커밋
Check-Then-Act 상황: 재촉 횟수 = 2인 상태에서 재촉하기 커밋 → 일기 작성 커밋
= 작성자 검증 시점과 실제 작성 시점의 불일치
정합성을 보장하면서 데드락을 해결할 수 있는 방안 검토
1. Redis
2. 애플리케이션 수준의 락
문제 1. 트랜잭션 범위와 락 범위의 불일치
문제 2. 다중 서버(분산, 스케일 아웃) 환경에서의 한계
3. 낙관적 락 (Optimistic Lock)
문제 1. 도입 범위, 복잡도에 비해 얻는 이득이 적다.
문제 2. FK로 인한 락 구조와 데드락에는 낙관적 락이 개입할 수 없다.
4. 비관적 락 (Pessmistic Lock)
문제 1. 정합성은 쉬운데, 성능과 확장성이 비싸다
문제 2. 이미 트랜잭션을 짧게 줄이는 방향으로 설계
문제 3. 비즈니스 규칙이 요구하는 것보다 과하게 보장
5. 조건부 업데이트 (Conditional Update)
장점: RMW를 한 번의 UPDATE로 수렴
장점: 도메인에 맞는 얇은 낙관적 락
단점: WHERE 조건의 설계와 확장성
2차 개선: 조건부 업데이트 + FK 제거 + 락 순서 정렬
Foregin Key 제거 (데드락 원인 일부 제거)
✅ 외래 키를 제거해도 괜찮은 이유
장점: 개발자가 락 순서 제어 가능
Lost Update 케이스: 재촉 횟수가 일치하지 않는 상황
⏸️ 적용 전(RMW + Lost Update)
▶️ 적용 후 (조건부 Update + 도메인 실패)
Check-Then-Act 케이스: 작성 차례가 아닌 사용자가 작성하는 상황
⏸️ 적용 전(검증 시점과 커밋 시점 사이의 갭)
▶️ 적용 후 (조건부 업데이트로 현재 작성자 보장)
Summary
시도한 것
결과 및 성과
Trade-off와 한계
적용 전/후 비교 (요약)
항목
적용 전
적용 후
Last updated