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 |