개요

Tiketeer 프로젝트의 티켓 구매 동시성 제어를 위해 낙관적 락, 비관적 락, redis 분산 락을 적용하고 각각 성능을 테스트해보았습니다.

테스트 시나리오

k6 script로 테스트를 진행하였습니다.

이때 vuser는 [10, 30, 50], ticket 수는 [10, 100, 1000] 으로 진행하였습니다.

대기열 적용을 통해 동시에 티켓 구매에 접근 가능한 user 수를 제한할 예정이므로 vuser는 상대적으로 작은 범위로 가정하였습니다.

1. 낙관적 락

낙관적 락에는 backoff에 관한 인자와 maximum retry 횟수에 관한 인자를 설정할 수 있습니다. (vuser, tickets) 시나리오별로 이에 대한 최적값을 찾으려고 합니다.

문제점

특정 티켓팅 하위의 티켓을 n개만큼 가져와 구매처리할 때 사용하는 쿼리는 아래와 같습니다.

SELECT t FROM Ticket t
WHERE t.ticketing.id = :ticketingId AND t.purchase IS NULL ORDER BY t.id

이는 동시에 들어온 여러 요청들이 항상 같은 티켓 레코드에 접근하게 합니다.

  1. 10개의 요청이 동시에 들어옴.
  2. 10개의 요청이 모두 동일한 ticket 레코드를 사용하려고 함.
  3. 이 중 제일 먼저 처리된 요청이 반영되고 나머지 9개 요청은 retry 시도.
  4. 9개의 요청이 다시 동일한 ticket 레코드에 접근함.
  5. 이 중 제일 먼저 처리된 요청이 반영되고 나머지 8개 요청은 retry 시도 ...

위의 절차를 반복하며 동시에 접근하는 유저 수에 따라 항상 retry가 발생하는 문제가 있습니다. 또한, 만 명의 요청이 동시에 들어올 때 maximum retry 횟수가 30인 경우 나머 70개의 요청은 무조건 실패하게 되는 문제가 있습니다.