줄 세우기
매표소 창구를 하나만 열고, 한 사람씩 들어와서 남은 자리를 확인하고 표를 받게 해요.
정확하지만, 모두가 한 줄로 기다려야 해요.
기록 불러오는 중…
1장
표는 100장인데 500명이 동시에 누르면, 서버는 몇 장을 팔까요?
1공연 표는 딱 100장. 9시 정각에 판매를 시작해요.
29시가 되자 500명이 같은 순간에 "예매" 버튼을 눌러요.
3서버는 한 명 한 명에게 "아직 자리 있어요"라고 답해요. 같은 순간이라 다 맞는 말처럼 보여요.
4표를 산 500명이 공연장에 왔어요. 그런데 자리는 표 100장만큼뿐이에요.
기록 불러오는 중…
실제 서버와 데이터베이스에서 500명이 한꺼번에 예매해요. 1초도 안 걸려요.
같은 조건(표 100장, 500명 동시)에서 세 가지 방법을 실제로 돌린 결과예요. 셋 다 자리 없이 들어온 사람은 0명이지만, 걸리는 시간과 수고가 달라요.
매표소 창구를 하나만 열고, 한 사람씩 들어와서 남은 자리를 확인하고 표를 받게 해요.
정확하지만, 모두가 한 줄로 기다려야 해요.
기록 불러오는 중…
일단 다 같이 시도하고, 내가 보는 사이 누가 먼저 가져갔으면 처음부터 다시 해요.
사람이 적을 땐 가볍지만, 몰리면 다시 하기가 폭증해요.
기록 불러오는 중…
사람이 몰리면 수 초~20초 넘게 걸릴 수 있어요.
"자리 확인"과 "표 주기"를 매표소가 한 동작으로 끝내요. 그 사이에 누가 끼어들 틈이 없어요.
가장 빠르고 정확해요. 조건이 단순할 때 쓸 수 있어요.
기록 불러오는 중…
같은 방법이라도 돌릴 때마다, 그리고 컴퓨터와 설정에 따라 걸린 시간과 다시 시도한 횟수가 달라져요. 그래서 카드의 숫자와 아래 "숫자로 본 결과"의 숫자가 다를 수 있어요.
SELECT … FOR UPDATEUPDATE … WHERE issuedCount < totalQuantityrunSimulation()이 POST /coupons/simulate를 보내요. 본문은 { users: 500, quantity: 100, strategy? }예요.CouponsController.simulate가 runSimulation 관문을 먼저 지나요.simulation_cooldown + Retry-AfterCouponStrategies.simulate가 쿠폰 sim-<전략>을 리셋하고, 가상 사용자 500명의 issue()를 동시에 던져요. 전략을 안 고르면 4개를 차례로 돌려요.{ results: [...] }로 돌려줘요. 전략마다 최종 행 상태, 요약, 스냅숏, 요청 500개 기록이 들어 있어요.useReplay).GET /coupons/:name/state?limit=10으로 실제 행을 다시 읽어요.| id | name | totalQuantity | issuedCount | version | updatedAt | CouponIssue 행 수 |
|---|---|---|---|---|---|---|
| 10 | sim-none | 100 | 1 | 0 | 2026-10-20 04:59:48.114 | 500 (초과 400) |
| 11 | sim-pessimistic | 100 | 100 | 0 | 2026-10-20 04:59:48.525 | 100 |
| 13 | sim-optimistic | 100 | 100 | 100 | 2026-10-20 04:59:49.781 | 100 |
| 12 | sim-atomic | 100 | 100 | 0 | 2026-10-20 04:59:49.925 | 100 |
500명 / 100장으로 전략 4개를 돌린 뒤 읽었어요. 마지막 칸은 CouponIssue 행 수를 센 값이고, 시각은 UTC예요.
issuedCount가 1에 머물렀어요 (lost update).POST /coupons/simulate 한 건만 보여요. 500명은 브라우저가 아니라 서버 안에서 동시에 돌아요.어떻게: 남은 수량을 읽고 → 남았으면 발급하고 → 카운터를 (읽은 값 + 1)로 저장합니다.
장점: 가장 단순한 코드. 단점: 여러 요청이 동시에 "아직 남았다"를 읽고 모두 통과 → 초과 발급. 카운터도 서로 덮어써서(lost update) 실제 발급 수와 어긋납니다.
이 전략으로 실행해 보세요.