내가 면접 전에 정리하면서 써둠
1. 30초 안에 100개 정도의 경품이 나가는 등 예상보다 유저가 많이 몰렸음
2. 원래 예상은 이것보다 훨씬 널럴한 이벤트였지만, 혹시나 하는 생각에 락을 걸어서 동시성 제어
3. 유저의 '따닥'을 클라이언트 단에서 혹시나 못 막는 문제를 막기 위해서 유저 정보로 락을 검 (인메모리 DB 단에서)
4. 유저가 이벤트에 참여 시도하는 즉시, 가능한 상품 목록 중에서 하나가 결정되고 해당 상품에 락을 검
5. 당첨된 상품에 락이 이미 걸려있다면 운이 좋은 유저가 먼저 선점했다는 뜻이기 때문에 가능한 상품 목록에서 지우고 최대 n회 재시도함
6. 유저가 당첨된 상품에 락이 안 걸려있다면 중복 당첨이 없다는 뜻이기 때문에, DB에서 유저의 시행 가능 횟수 차감, 해당 상품 상태 변경 등 처리함
7. 처리 완료되면 당연히 락 품
8. 그 결과 경품 당첨됐는데 왜 상품 안 주냐 등의 CS가 없었고, 협업한 회사에서도 갑자기 요청한 프로젝트가 문제없이 진행된 것에 대해 크게 만족함
9. 원래는 가능한 상품 ID 목록 인메모리 DB Array 형태로 저장해두고 SPOP으로 지우면서 더 빨리 처리할려고 했는데, 생각보다 고쳐야 되는 부분이 많아서 (Django 빌트인 cache에서 SPOP 지원 안 함) 개발 공수 고려해서 당첨 가능한 상품 목록 가져오는 건 DB에서 함
운이 나쁘게 n회 요청할때까지 충돌이 일어나서 결국 못받은 유저가 생겼다면?
상품이 몇 개 안 남은 시점에서 그럴수도 있는데, 재고 소진되는 속도 생각하면 '아 ㅅㅂ 벌써 나갔네' 하면서 납득했을듯
@글쓴 백갤러(1.230) 상품에 락을 건다는건 진짜 db락을 건다는거임 아니면 논리적 락(특정 칼럼에 예약자 id를 외래키로 연결한다던지)을 걸고 compare and swap 방식으로 업데이트 한다는거임?
@밀우 인메모리DB에서 테이블이름:id로 간단하게 락 걸고, 성공하면 DB에서도 상태 업데이트함