쿠폰을 발급하는데 동시성 문제? 동시성 문제가 뭐지? 먼저 동시성 문제란 두 개 이상의 쓰레드가 동시에 같은 자원에 접근했을 때, 발생할 수 있는 문제이다. 어떤 문제인지 알아보자.

쿠폰의 남은 갯수가 1개이고, 사용자 A와 B가 동시에 쿠폰 발급을 진행하려 한다.(트랜잭션 격리수준은 mysql innoDB의 기본전략인 Repeatable Read를 전제로 진행합니다. 트랜잭션 격리수준에 대해 모른다면 꼭 찾아보세요.)

Untitled

위 그림을 보면 결국엔 둘 다 쿠폰 발급에 성공하게 됩니다. 이것은 트랜잭션 수준이 Serializable이 아닌 이상 트랜잭션이 관리밖의 문제입니다. 또한 최종 쿠폰 발급 가능 갯수가 0이 아닌 -1이 되어야 할 것 같은데 0입니다. 이것을 두번의 갱실 분실 문제(Second Lost Updates Problem)라고 합니다.

사용자 A의 수정사항은 사라지고 나중에 완료한 사용자 B의 수정사항만 남게 되는 문제인 것이죠.

이 문제를 해결하기 위해서 3가지 선택 방법이 존재합니다.

  1. 마지막 커밋만 인정하기
  2. 최초 커밋만 인정하기
  3. 커밋된 갱신 내용을 병합하기(A와 B의 수정 사항을 병합하여 적용하는 방법)

우리 프로젝트는 여기서 2번째 방법인 최초 커밋만 인정하기 방법은 선택하였다.

기본적으로 우리가 가지는 요구사항은 아래와 같다.

먼저 들어온 요청이 먼저 처리되어야 한다. 즉 먼저 들어온 사람이 먼저 쿠폰 발급에 성공(쿠폰 발급 갯수가 남아있다면)하든 실패(쿠폰 발급 갯수가 모두 소진됬다면)하든 해야한다.

때문에 1번의 해결 방법은 맞지 않고 3번의 방법을 사용하기엔 너무나 복잡하다. 그래서 2번 방법을 선택한 것이다. 2번 방법을 구현하는 여러 방법이 있지만 그 중에 낙관적 락, 비관적 락을 이용해 보았다.