flab

티켓팅 서비스 내 동시성 문제 해결(RDB 동시성 문제)

Lee_SJ 2025. 4. 9. 21:31

사용자는 티켓팅 예약을 통해 티켓팅을 할 수 있습니다.

이 때 유저는 좌석을 선택해서 좌석이 이미 선택되지 않은 경우 예약이 가능하고 콘서트에서는 예매 가능 좌석이 하나 줄어듭니다.

 

참고로 제가 테스트한 콘서트의 정보는 다음과 같습니다.

해당 콘서트는 concert_seat을 1~80까지 가지고 있습니다.(80건의 좌석예매 가능)

id name artist_name remaining_seat status concert_hall_name
1 Shining Star 콘서트 엑소 80 OPEN 올림픽홀

 

이 콘서트를 300명이 동시에 접속하여 예약 시도해보겠습니다.

총계: 90

id member_id seat_id status created_at
1 5 10 PENDING  2025-04-08 09:02:15
2 258 10 PENDING  2025-04-08 09:02:15
3 239 11 PENDING  2025-04-08 09:02:15
4 240 71 PENDING  2025-04-08 09:02:15
5 33 11 PENDING  2025-04-08 09:02:15
... .. .. ...  

 

다음과 같이 중복된 좌석에 여러 멤버가 동시에 예약된 것을 볼 수 있습니다.

그러면 이제 남은 좌석은 0이어야 하는데 어떨까요?

id name artist_name remaining_seat status concert_hall_name
1 Shining Star 콘서트 엑소 45 OPEN 올림픽홀

 

다음과 같이 제대로 반영이 되지 않았습니다.

 

 

해결과정

3가지 동시성 제어 방법을 활용하여 해결해 보겠습니다.

참고로 이 시나리오는  2000건의 티켓팅 요청을 한 꺼번에 요청했을 때를 가정으로 합니다.

1) Pessimistic lock
2) MySQL named lock
3) Redisson distributed lock

 

1. Pessimistic lock

Pessimistic lock 구현 방식

- https://github.com/f-lab-edu/ticket-play/pull/25 참고해주세요

 

단일 서버에 요청시
  요약 TPS
1회차 avg=3144.86ms min=4.72ms max=12808.07ms p(90)=5575.39ms p(95)=6502.86ms 27.23
2회차 avg=2163.78ms min=4.92ms max=8458.05ms p(90)=3851.17ms p(95)=4797.15ms 30.38
3회차 avg=2333.26ms min=3.27ms max=10138.64ms p(90)=3961.47ms p(95)=4841.58ms 28.75

 

3개의 서버에 요청시
  요약 TPS
1회차 avg=5491.90ms min=2.69ms max=25375.15ms p(90)=9844.93ms p(95)=11596.21ms 19.92
2회차 avg=3997.24ms min=0.23ms max=14279.96ms p(90)=7184.11ms p(95)=8304.17ms 19.20
3회차 avg=3806.98ms min=2.57ms max=16156.09ms p(90)=6575.27ms p(95)=7411.96ms 19.87

 

 

2. Mysql Named Lock - 다시보기

Mysql Named Lock구현 방식

- https://github.com/f-lab-edu/ticket-play/pull/26 참고해주세요

 

결과

단일 서버에 요청시

 

  요약 TPS
1회차 avg=3135.75ms min=5.15ms max=11750.93ms p(90)=5542.29ms p(95)=6329.77ms
23.46
2회차 avg=2884.40ms min=3.89ms max=10696.71ms p(90)=5228.42ms p(95)=6177.23ms  24.95
3회차 avg=2713.96ms min=2.90ms max=11311.73ms p(90)=4890.68ms p(95)=5684.11ms 25.87
3개의 서버에 요청시
  요약 TPS
1회차 avg=3922.97ms min=0.85ms max=22913.50ms p(90)=3739.82ms p(95)=5040.52ms 17.84
2회차 avg=1804.85ms min=68.89ms max=17336.41ms p(90)=4323.92ms p(95)=6060.52ms 17.64
3회차 avg=1777.94ms min=68.47ms max=8585.91ms p(90)=3391.41ms p(95)=4065.22ms 17.78

3. Redisson 

Mysql Named Lock구현 방식

- https://github.com/f-lab-edu/ticket-play/pull/27 참고해주세요

 

결과

단일 서버에 요청시
  요약 TPS
1회차 avg=1370.75ms min=8.21ms max=9682.03ms p(90)=3089.21ms p(95)=4096.18ms 25.67
2회차 avg=1789.75ms min=3.21ms max=12309.03ms p(90)=5492.21ms p(95)=8372.18ms 20.82
3회차 avg=2851.37ms min=1.99ms max=18702.96ms p(90)=7894.18ms p(95)=10031.06ms 25.09

 

3개의 서버에 요청시
  요약 TPS
1회차 avg=8529.35ms min=7.35ms max=23291.16ms p(90)=16350.94ms p(95)=17869.40ms 12.72
2회차 avg=5965.53ms min=3.68ms max=22779.43ms p(90)=13243.79ms p(95)=16238.73ms 13.83
3회차 avg=5097.16ms min=2.53ms max=21780.83ms p(90)=11444.30ms p(95)=13900.51m 13.36