1. 테스트 환경
- 테스트 도구: nGrinder
- 테스트 스크립트: 로그인 후 쿠폰 발급 API 호출 (동일한 API 테스트)
- Vuser 수: 99명 → 99명의 가상 사용자가 동시에 부하를 발생시킴
- Processes/Threads: 3 프로세스, 각 프로세스당 33 쓰레드
- Duration: 1분 → 테스트는 1분간 진행
- Ramp-Up: 비활성화 (즉시 99명의 사용자 부하 발생)
- 테스트 조건:
- 비관적 락: 데이터베이스 수준에서 락 관리
- 레디스 락: RedissonClient를 이용한 분산 락 관리
- 낙관적 락: @Retryable을 활용하여 낙관적 락 충돌 시 재시도
2. 결과 비교
지표 | 비관적 락 | 레디스 락 | 낙관적 락 |
---|
TPS (초당 처리율) | 90.5 | 3,938.0 | 94.8 |
Peak TPS (최대 TPS) | 117 | 4,811 | 115 |
Mean Test Time | 1,089.81 ms | 22.95 ms | 1,043.60 ms |
Executed Tests | 4,958 | 214,969 | 5,176 |
Successful Tests | 4,958 | 214,969 | 5,176 |
Errors | 0 | 0 | 0 |
3. 성능 분석
비관적 락
- TPS: 90.5
- Mean Test Time: 1,089.81 ms
비관적 락은 데이터베이스 수준에서 자원에 대한 락을 독점하기 때문에 경합이 심해질수록 대기 시간이 길어지고, 동시 요청을 처리하는 데 병목이 발생.
- 약 5,000건의 요청만 성공적으로 처리되었으며, 초당 처리량이 90~117 TPS로 제한.
주요 원인:
- 락을 획득한 트랜잭션이 완료될 때까지 다른 쓰레드가 대기해야 함.
레디스 락
- TPS: 3,938.0
- Mean Test Time: 22.95 ms
레디스 락은 Redis의 분산 락 기능을 활용하여 더 빠르게 락을 관리하고 해제. 트랜잭션 부담이 줄어들어 더 많은 동시 요청을 효율적으로 처리.
- 약 214,969건의 요청을 처리하였으며, 초당 처리량은 3,938 TPS에 달한다.
주요 원인:
- 레디스 락은 락의 획득/해제가 비동기적이고 빠르게 이루어지며, 데이터베이스에 직접 락을 걸지 않음.
낙관적 락
- TPS: 94.8
- Mean Test Time: 1,043.60 ms
낙관적 락은 트랜잭션 시작 시에는 락을 걸지 않고, 커밋 단계에서만 충돌을 감지. 충돌 발생 시 @Retryable을 활용해 재시도 로직을 처리.
- 초당 처리량은 약 94.8 TPS로 비관적 락과 유사하나, 평균 응답 시간이 소폭 개선됨.
재시도 관련 데이터:
주요 원인:
- 데이터베이스에 락을 걸지 않고도 충돌을 효율적으로 처리.
- 하지만 충돌이 잦을 경우 재시도 로직으로 인해 TPS가 제한적.
4. 결론
- 레디스 락은 비관적 락과 낙관적 락 대비 성능이 월등히 우수합니다.
- 특히 TPS와 평균 응답 시간에서 큰 차이를 보이며, 동시 요청이 많은 환경에서 레디스 락이 훨씬 더 적합.
- 낙관적 락은 비관적 락과 유사한 성능을 보이지만, 재시도 로직으로 인해 시스템 자원 사용량이 다소 증가할 수 있음.
비관적 락은 데이터 무결성이 절대적으로 중요한 시스템에 적합. |
레디스 락은 동시성이 중요한 대규모 시스템에서 성능 병목을 해소하는 데 효과적. ✅
낙관적 락은 경합이 적은 환경에서 데이터 처리 성능을 높이는 데 유리. |