1. 문제 인식: RDBMS 비관적 락의 한계
앞선 글에서의 결론은 Redisson 분산락을 적용하여 동시성을 제어하고 DB 레벨의 비관락을 제거해줌으로써, 문제가 되었던 DB 병목으로 인한 문제를 해결하고자 함이었다.
- 현상: 데이터 정합성을 위해
SELECT ... FOR UPDATE를 사용했으나, DB 커넥션 풀 고갈(Blocking I/O)로 전체 시스템 마비.
- 문제점:
- 재고가 없는 상황에서도 락 대기열 발생.
- 주문뿐만 아니라 무관한 다른 서비스까지 영향이 전파될 가능성을 내포.
- 단순 DB 락만으로는 수십만 건의 트래픽을 감당 불가하다고 판단.
2. [1차 시도] Redis 분산락 도입
- 접근:
Redis 분산락 + DB 낙관적 락으로 DB 부하를 줄이려 함.
- 문제: Tx 전체에 락을 거는 건 비관적 락과 비용 차이만 있을 뿐 똑같다. 락의 범위를 '재고 차감' 단위로 줄여라.
3. [2차 시도] Redis Lua Script + JPA 조회 시 비관락 제거
- 설계:
- Redis: Lua Script로 원자적 재고 차감.
- DB:
Select(조회) -> Logic(차감) -> Update(저장) 수행.
- 보상: DB 실패 시 Redis 재고 복구 (
Increase).
- 결과 : 갱신 손실 발생.
- Redis는 1000명을 정확히 통과시켰으나, 그 1000명이 DB에 동시 접근하여
Select와 Update 사이의 시차로 인해 재고 정합성이 깨짐 (1000개 판매 후 DB 잔고 841개 등).
- 충돌이 많을 것으로 예상해서 낙관락은 적용안하고 테스트 해봤음
4. [3차 시도 (해결)]: Redis + DB Direct Update