serversim
시뮬레이터내 Documents템플릿가격
…
…
블로그
🔥

Flash Sale 1만 명이 같은 상품 → DB 직렬화 → 결제 실패

2026-05-14·7분·
hot-keypaymentflash-saledatabase

Hot key contention 도메인. 같은 row를 동시 update 시 RDBMS row lock 직렬화 → 처리 못한 요청 backpressure → 앱 thread 가득 → cascading. 해결책 4가지 (Redis INCR / sub-counter / Kafka serial / cell architecture).

상황

Flash sale — 인기 상품 1만 명이 동시 클릭. UPDATE inventory SET qty = qty - 1 WHERE id = 123 를 모두 같이 실행.

결과: DB row lock 직렬화. 한 시점에 1개만 처리. 나머지 9999개 대기 → caller thread 점유 → upstream backpressure → cascading.

시뮬 결과

hot-key-contention preset에서:

  • 2000 RPS burst
  • MySQL lock acquire 2996회 / wait 3033회 / 동시 wait 38건
  • Spring queue 400 가득 → 54% drop (queue-full)
  • 도메인 정확: DB는 안 죽지만 (CPU 14%) 앱이 죽음

왜 단순 scale-out 안 되나

App 100대로 늘려도 — 모든 트래픽이 같은 row로 모이면 DB row lock은 1개. 100대 app은 99% 대기. DB shard 100개로 분산해도 같은 product 1개는 한 shard로 — 똑같이 직렬화.

해결책 4가지

1. Redis INCR Counter (가장 흔함)

DECR inventory:123 — Redis single-thread + atomic. 100k+ ops/s. Redis 값이 정답, DB는 비동기 동기화 (eventual).

Trade-off: Redis 죽으면 재고 데이터 손실. AOF persistence + replica 필수.

2. Sub-counter 분산

재고 1000개를 10개 sub-counter로 분산 (각 100개). user_id % 10 으로 라우팅. 각 counter는 다른 row → 병렬 처리.

Trade-off: 재고 종료 임박 시 일부 counter는 0, 다른 counter는 남아있을 수 있음. 마지막엔 통합 필요.

3. Kafka Serial Consumer

모든 차감 요청을 Kafka로 publish. partition key = product_id로 같은 상품은 같은 partition. Consumer 1개가 partition 순서대로 처리 (자연스러운 직렬화).

Trade-off: 사용자 대기 시간 (Kafka lag). 응답은 "ack 받음"만 — 결과는 async 알림. 대용량 flash sale에 적합 (몇 초 lag OK 환경).

4. Cell-based Architecture

시스템을 cell로 분리. 각 cell은 독립 DB + app. user를 cell에 sticky 매핑. 한 product의 재고도 cell별로 사전 할당. cell 내부만 직렬화, cell 사이는 독립.

Trade-off: 인프라 N배. 일반 production보단 amazon 같은 hyper-scale에서 사용.

실 사례 — 좌석 예약

영화 / 콘서트 좌석 예약도 같은 패턴. 인기 콘서트 오픈 시 같은 좌석 row update 1만 명 동시.최선: Redis INCR + 좌석 별 sub-counter. 예매 사이트들이 "좌석 일시적으로 잡혔습니다" 메시지 띄우는 이유.

면접 답변 템플릿

"Flash sale의 문제는 scale-out으로 안 풀린다는 점입니다. DB row lock이 자연스러운 직렬화 지점이라 instance를 늘려도 같은 row를 기다리니까 의미가 없습니다.

해결책 4가지 중 일반적으로 Redis INCR counter를 씁니다. 단점은 Redis 죽었을 때라 AOF + replica 필수. 대용량 (수만 RPS+)이면 Kafka serial consumer로 가서 사용자 ack만 즉시 반환, 실제 처리는 async."
🧪 시뮬레이터에서 직접 확인

이 글의 시나리오는 시뮬레이터 안에서 즉시 실행할 수 있습니다. 노브를 만지며 결과 변화 관찰.

시뮬레이터 열기 →
← 블로그 목록
© 2025-2026 serversim · 아키텍처 시뮬레이션 도구