inflearn logo
강의

講義

知識共有

AI時代のジュニアのための実践システム設計:経験値の代わりに補います

トラブルシューティング・ケーススタディ — P大手コマース vs W EC、同じ問題に異なる解決策

트러블슈팅 케이스 스터디 - P 대형 커머스

13

ghtyu21

投稿した質問数 2

0

안녕하세요! 강사님

좋은 강의 감사합니다! 덕분에 공부가 잘 되고 있습니다. 다른 Q&A도 좋은 질문과 답변으로 많은 도움이 되고 있습니다.


섹션 3 19번 강의 관련해서 질문이 있습니다.

DB에서 Redis 재고 버퍼에 이벤트 시작 전 물량을 적재하신다고 하셨는데, 제가 경험이 없어서 적재한다는걸 이해를 잘 못했습니다.

적재한는 방법은 redis cli로 직접 적재하나요? 아니면 첫 요청은 캐시 미스면 db를 바라보게 한 후 이후 캐시에 물량을 저장하나요? 아니면 어드민같은 백오피스 서비스에 관련 로직이 있나요?



kotlin spring-boot kubernetes 아키텍처 kafka redis prometheus

回答 2

1

newnormal

안녕하세요, 좋은 질문 감사합니다.

말씀하신 세 가지 중에서는 세 번째, 어드민(백오피스)에 적재 로직을 두는 방식이 일반적입니다.

나머지 두 방식이 왜 맞지 않는지부터 보시면 "적재"가 무엇인지 더 잘 보입니다.


1. 첫 요청이 캐시 미스면 DB를 보고 Redis에 저장하는 방식: 재고에는 쓰면 안 됩니다

상품 상세 같은 조회용 캐시라면 이게 정석입니다. 그런데 이벤트 재고에 쓰면 문제가 두 가지 생깁니다.

- 오픈 순간 몰린 요청이 전부 동시에 캐시 미스를 보고 DB로 갑니다. 피하려던 "DB 한 행에 10만 명" 상황이 그대로 다시 생깁니다.

- 더 위험한 건 덮어쓰기입니다. 서버 여러 대가 동시에 미스를 보고 각자 DB의 100을 Redis 에 SET 하면, 그 사이 이미 97까지 깎인 값이 다시 100이 됩니다. 덮어쓴 만큼 더 팔립니다. 오버셀을 막으려고 만든 구조가 오버셀을 만드는 셈입니다.

핵심은 재고 버퍼가 "캐시"가 아니라는 점입니다. 캐시는 DB 가 정답이라 언제 지우고 다시 채워도 괜찮습니다. 반면 재고 버퍼는 이벤트가 진행되는 동안 Redis 값이 "지금 남은 수량"의 정답이고, DB 는 이벤트가 끝난 뒤 정산으로 맞춥니다(3-5). 그래서 요청이 들어오기 전에 딱 한 번 올려 두고 시작해야 합니다.


2. redis-cli 로 직접 넣는 방식: 로컬과 실습에서는 괜찮습니다

3-7 실습 코드의 reset() 이 하는 일도 결국 SET 한 줄입니다. 하지만 운영에서는 피합니다. 사람이 손으로 치면 숫자를 틀려도 아무도 모르고, 누가 언제 올렸는지 기록도 남지 않습니다. 또 재고 키 말고도 구매자 Set 같은 키를 함께 맞춰야 해서 실수할 자리가 많습니다. 운영 Redis 에 사람이 직접 접속하는 것 자체를 막는 회사도 많습니다.


3. 어드민·백오피스에 로직을 두는 방식: 보통 이렇게 합니다

흐름은 대략 이렇습니다.

① 운영자가 어드민에서 이벤트를 등록합니다. 상품, 물량(예: 100개), 시작 시각을 정합니다.

② 이 물량을 DB 재고에서 떼어 둡니다. 일반 판매 재고에서 100을 빼서 이벤트용으로 따로 기록해 두는 겁니다. 그래야 같은 물건이 일반 판매와 이벤트에서 동시에 팔리지 않습니다. 강의에서 "DB 에서 미리 떼어"라고 한 게 이 단계입니다.

③ 시작 전에(예: 10분 전) 스케줄러가 돌거나 운영자가 "오픈 준비" 버튼을 누르면, 서버가 Redis 에 수량을 올립니다. 이때 SET NX(키가 없을 때만 저장)로 넣어서, 버튼이 두 번 눌리거나 서버 두 대가 동시에 돌아도 이미 올라간 값을 덮어쓰지 않게 합니다.

④ 올린 값을 다시 읽어서 확인합니다. 어드민 화면에 "DB 할당 100 / Redis 적재 100" 처럼 보여 주면 사람이 눈으로 검증할 수 있습니다.

⑤ 시작 시각 전까지는 구매 API 가 "오픈 전"으로 막고, 시각이 되면 엽니다.

⑥ 끝나면 Redis 에 남은 수량과 판매 기록으로 DB 를 정산하고, 남은 물량은 일반 재고로 돌려놓습니다.

③을 코드로 쓰면 이 정도입니다.

val loaded = redis.opsForValue().setIfAbsent("event:$eventId:stock", quantity.toString())

// false 면 이미 적재된 것이니 덮어쓰지 않고 운영자에게 알린다


마지막으로 "이벤트 중에 Redis 가 죽으면?"도 같은 원리입니다. 이때도 캐시처럼 DB 값을 그대로 다시 올리면 안 됩니다. DB 할당량에서 지금까지 팔린 수량을 빼서 다시 계산한 값을 올려야 합니다. 3-3에서 "DB 원본에서 다시 계산해 올릴 수 있어야 한다"고 한 게 이 이야기입니다.


0

ghtyu21

답변 감사합니다~

제가 아직 경험이 부족한 신입 개발자라 답변 주신 내용이 정말 도움이 되고 있습니다!

장바구니 질문

0

11

1

강의 내용 질문 `[실습] MDC·UTM·세션ID로 "돈 버는 로거" 만들기`

0

15

1

26년 11월 기준 쿠버네티스 설치 가이드 요청

0

14

1

vagrant 가 잘안됩니다.

0

18

1

화면이 안나와요

0

22

2

kubeinstall.sh 오류 확인 요청드립니다.

0

16

1

강의와 상관 없지만 여쭤봅니다.

0

35

1

[github fork]tz-argocd-repo

0

36

1

강의 소스코드는 어디서 다운받을 수 있나요?

1

55

2

팔로워수,팔로잉수 조회 설계

1

38

1

화질 문의

0

65

1

JpaPagingItemReader는 좋은게 없는거야..??

0

56

1

현재 배포 아키텍처에서 Kafka 테스트 배치 및 구성 방향 질문드립니다.

0

41

1

nginx 질문드려도될까요?

0

46

1

실습용 VM 시간 불일치로 인한 Calico CNI 인증(Unauthorized) 에러 조치 문의

0

62

2

리프레시토큰

0

52

1

안녕하세요.

0

122

3

DB 연결 후 회원가입 시 생성되는 id 번호 질문

0

56

2

안녕하세요aks에대한 문의드립니다.

0

38

1

30강

0

59

1

파킹 페이지와 대기열 큐 질문입니다.

1

58

1

구현 방법에 대한 문의

0

100

2

MSA 통신방식에 대해서 질문 있습니다.

0

65

1

안녕하세요 질문있습니다.!

0

94

2