실시간 유저 랭킹 조회 DB에서의 조회와 Redis를 캐싱(Cacheable 사용)한 것에서의 비교분석
DB에서 유저 랭킹 조회
레디스에서 조회
위 그래프들을 표로 분석
[내가 구현한 기능]
포인트에 따른 실시간 유저 랭킹
[주요 로직]
실시간 유저 포인트 랭킹 기능에서 Redis의 Sorted Set 자료 구조와 TTL(Time to Live) 기능을 사용하여 빠른 조회 성능을 확보하고 데이터 일관성을 유지했습니다. Sorted Set을 통해 유저 포인트를 기준으로 자동 정렬된 상태로 랭킹을 관리하며, TTL을 설정해 캐시 데이터가 일정 시간이 지나면 자동으로 갱신되도록 구현했습니다.
[배경]
실시간 포인트 랭킹 조회 기능이 높은 트래픽 상황에서도 빠른 응답 속도를 유지할 수 있도록 최적화가 필요했습니다. 기존 방식으로 DB에서 직접 실시간 랭킹 데이터를 조회할 경우 지속석으로 쿼리를 호출이 되다보니 전체 응답 속도가 느려지는 문제가 발생했습니다. 특히, 실시간 조회이다보니 빈번한 데이터 접근이 필요하기 때문에 고속의 메모리 기반 접근 방식이 필요하다고 판단했습니다.
[요구사항]
- 실시간 랭킹 조회 시 빠른 응답 속도를 유지하여 유저 경험을 개선해야 합니다.
- 트래픽 증가에 따라 데이터베이스 부하를 줄이면서도 일관성을 유지할 수 있는 시스템이 필요합니다.
- 랭킹 조회 시 데이터가 자동 정렬된 상태를 유지하여 실시간으로 최신 순위를 반영해야 합니다.
[선택지]
- RDBMS 사용: 기존 DB 접근 방식을 통해 직접 랭킹 데이터를 조회하는 방식입니다. 이는 강력한 트랜잭션 관리와 데이터 일관성을 보장하지만, 빈번한 조회 시 성능 저하가 발생할 수 있습니다.
- Redis의 Sorted Set과 TTL 사용: 메모리 기반의 Redis를 활용하여 빠른 조회 성능과 자동 정렬을 제공하는 Sorted Set을 사용합니다. TTL 기능을 통해 캐시 데이터를 주기적으로 갱신하여 실시간 데이터 일관성을 유지할 수 있습니다.
[의사결정/사유]
- Redis 사용 이유: Redis는 메모리 기반 저장소로, 데이터 접근 속도가 매우 빠릅니다. 또한, Sorted Set 자료 구조를 통해 각 유저 포인트를 기준으로 자동 정렬된 상태를 유지할 수 있어 실시간 랭킹에 최적화된 선택입니다.
- RDBMS와의 차이점: Redis는 Key-Value 형태의 저장소로, 빠른 응답과 다양한 자료 구조(Sorted Set, Hash, List 등)를 제공해 실시간 데이터 조회와 캐싱에 적합합니다. 반면, RDBMS는 관계형 데이터베이스로, 디스크 기반의 저장 방식과 트랜잭션 관리에 최적화되어 있습니다.
- Sorted Set과 TTL의 필요성: Sorted Set은 각 요소에 점수를 할당하여 자동 정렬된 상태로 유지하는 자료 구조로, 내부적으로 Skip List를 사용하여 O(log n) 시간 복잡도를 제공합니다. TTL을 설정하여 데이터가 일정 시간이 지나면 자동 만료되도록 함으로써, 데이터 일관성을 유지하면서도 실시간 조회 성능을 높일 수 있습니다.
[성과]
Redis의 Sorted Set과 TTL을 사용한 캐싱 덕분에 실시간 유저 포인트 랭킹 조회 기능의 응답 속도가 크게 개선되었습니다. Redis의 메모리 기반 접근 방식 덕분에 고속의 처리량(throughput)과 짧은 지연 시간(latency)을 제공할 수 있었습니다.
- 트랜잭션 처리 속도: DB 접근 시 약 140 트랜잭션/초에서 Redis 캐싱으로 약 1,800 트랜잭션/초로 개선되었습니다.
- 평균 응답 시간: DB 접근 시 약 26,000ms 에서 Redis 캐싱으로 약 210ms 로 크게 단축되었습니다.
- 최대 스레드 수: DB 접근 시 약 1,000 스레드에서 Redis 캐싱으로 약 440 스레드로 감소하여, 효율적인 자원 사용이 가능해졌습니다.
[회고]
Redis의 Sorted Set과 TTL을 활용한 캐싱을 통해 실시간 랭킹 조회 성능을 크게 개선할 수 있었습니다. 특히 Sorted Set의 자동 정렬 기능 덕분에 추가적인 정렬 로직 없이 유저 포인트 기준으로 빠르게 순위를 관리할 수 있었습니다. TTL 설정으로 인해 캐시 데이터가 일정 시간 후에 자동 갱신되어, 데이터 일관성 측면에서도 효과적이었습니다.
다만, 실시간 데이터의 빈번한 변경 상황에서 캐시와 DB 간 일관성을 더욱 강화할 필요가 있습니다. TTL이 적용되어 있지만, 더 짧은 갱신 주기를 통해 실시간성을 높이거나, 비동기 업데이트를 추가하여 데이터 불일치를 최소화할 수 있는 방안을 검토하고 있습니다. 이를 통해 유저에게 신속하고 정확한 데이터를 제공하며, 시스템의 신뢰성을 더욱 높일 수 있을 것으로 예상하고 있습니다.
[문제 해결 과정]
성능 개선 요약
DB를 직접 조회하는 방식에서 Redis의 Sorted Set과 캐싱을 사용한 방식으로 전환하여, 실시간 유저 포인트 랭킹 조회 시 성능을 최적화했습니다. 이를 통해 응답 속도가 빨라지고 DB 부하가 크게 줄었습니다.
문제 정의
- 실시간 유저 포인트 랭킹 조회 시 트래픽 증가에 따라 응답 속도가 느려지고, DB에 과부하가 걸리는 문제가 발생했습니다.
- 특히 DB에서 실시간 랭킹 데이터를 직접 조회하는 경우, 빈번하게 유저 랭킹을 조회해서 상위 3명만 조회하는 쿼리로 인해 성능이 저하되고 전체 시스템 응답 속도가 느려졌습니다.
가설
실시간 랭킹 데이터를 DB에서 직접 조회하는 방식이 성능 저하의 주요 원인일 수 있습니다. Redis의 Sorted Set과 캐싱을 통해 자주 조회되는 랭킹 데이터를 관리하면, 데이터베이스 접근 횟수를 줄이고 조회 성능을 높일 수 있을 것으로 예상됩니다.
해결 방안
- Redis의 Sorted Set 사용: 유저 포인트를 스코어로 설정하여 Sorted Set에 저장하고, 실시간으로 자동 정렬된 상태를 유지하여 랭킹 조회에 최적화된 데이터를 제공합니다.
- TTL(Time to Live) 적용: TTL 기능을 통해 캐시 데이터가 일정 시간이 지나면 자동으로 갱신되도록 설정하여, 데이터 일관성을 유지하면서 최신 랭킹 데이터를 제공합니다.
- DB와 Redis 간의 데이터 일관성 관리: 포인트 변경 시 DB에 기록하고, 트랜잭션 커밋 후 Redis에 반영하여 데이터 일관성을 유지할 수 있도록 설정했습니다.
해결 완료
- 결과: Redis의 Sorted Set과 캐싱을 통해 실시간 유저 포인트 랭킹 조회 기능의 응답 속도가 크게 개선되었습니다.
- 전후 데이터 비교: DB 접근 방식일 때는 약 140 트랜잭션/초, 평균 응답 시간 26,000 ms였으나, Redis 캐싱 방식으로 전환 후 약 1,800 트랜잭션/초, 평균 응답 시간 210 ms로 개선되었습니다.
'PORTFOLIO > TROUBLESHOOTING' 카테고리의 다른 글
[ACE Hand Wash - 트러블 슈팅] Bootstrap 첫 걸음: JSP 충돌 해결 스토리 (0) | 2025.01.09 |
---|---|
[library- 트러블 슈팅] 패키지 설치의 덫: GPG 인증 문제 해결기 (0) | 2025.01.08 |
[CodeChef - 트러블 슈팅] 인덱싱: 데이터 속도 전쟁에서 살아남기! (1) | 2025.01.06 |
[CodeChef - 트러블 슈팅] 실시간 알림의 비밀: RabbitMQ로 댓글 알림 시스템 구축하기 (0) | 2025.01.06 |
[CodeChef - 트러블 슈팅] EC2 독립 선언: 한 서버에 갇힌 서비스들을 해방하다. (0) | 2025.01.06 |