티스토리 뷰
문제 상황 & 접근
- DB 페이징 쿼리 기반으로 랭킹을 조회하는데 있어 성능이 좋지 못함
오프셋 기반 페이징이라 데이터가 많아질 수록 느려지기에 Redis를 통해 랭킹 시스템을 구축하고자 결정
적용
기존 쿼리
- Pageable 를 통해 데이터베이스의 데이터를 정렬하여 오프셋 기반 페이징을 수행한다.
- where 절의 조건은 랭킹에 포함할 멤버인지 확인하는 정도의 조건이다.
- DB에서 순위를 매겨야 하기에 정렬은 불가피 했고, 서비스 요구사항에 의해 페이징도 필요했다.
(요구사항이 아니더라도 많은 데이터가 있는 경우 페이징이 없다면 전체조회는 위험하다.)
- Redis의 자료구조 중 하나인 Sorted Set은 member를 score 기반으로 정렬하여 저장한다.
- 순위를 매겨 조회해야하는 경우 효과적이다.
- 페이징과 같이 부분만 조회하는 기능도 제공하며, 그룹별 순위를 매겨 조회하는 기능 또한 가능하여 효과적으로 서비스 요구사항을 만족시키며 구현할 수 있을 것이라 기대했다.
Redis의 Sorted Set 활용
- redisTemplate의 ZSet에 조회를 수행한다.
다른 정보 함께 저장하는 방법에 대한 고민
- 랭킹 조회시 다른 정보들이 함께 조회되어야 했다.
- ZSet 에는 여러 정보를 함께 저장하기엔 한정적이었다. 별도의 자료구조에 나머지 정보를 저장하는게 좋을 것이라 판단했다.
- String 자료구조에 Json 형태로 변환하여 저장하였고, 조회할때 key 값을 통해 읽어오도록 구현하였다.
- String 자료구조는 get으로 조회시 O(1) 의 시간복잡도로 처리 가능하기에 조회 성능을 기대하고 사용했다.
- String 자료구조가 아닌 다른 방법은?
- Hash 자료구조로 항목별로 key-value 형태를 통해 저장하는 방법을 생각해볼 수 있다.
- Json 변환과정을 거치지 않아도 된다는 장점이 있으며 일부 개별 항목에만 접근할때 효과적이다.
- 하지만, json을 dto로 변환한 이후 바로 응답 body에 사용하고 개별 항목 접근은 없었기 때문에 굳이 Hash에 요소 하나하나 저장하지 않아도 된다고 판단하여 String에 저장하기로 했다.
결론
- DB에 5만 건의 row를 삽입한 이후 부하테스트를 통해 평균 Latency를 확인하였다.
- 기존 랭킹시스템에 비해 4.58배 개선되었다.
(Before) DB Paging Query [120.44ms]
(After) Redis Sorted Set [26.26ms 4.58배 개선]
분석
- 정렬되어 저장되는 자료구조를 사용하여 DB를 통해 매번 정렬하면서 부분만 조회하는 방법보다 더 나은 성능을 보였다.
- 페이징 자체도 최적화하는 방법이 있다고 알고 있지만 그러한 방법 보다는 정렬하는 작업 또한 고려해 Redis Sorted Set으로 이전하여 성능을 높일 수 있었다.
'프로젝트 탐구 > GitRank' 카테고리의 다른 글
Github API의 느린 응답 이슈 개선을 위한 스케줄링을 통한 DB 업데이트 (0) | 2024.03.25 |
---|---|
DB 중복 insert 동시성 이슈 개선을 위한 Lock 전략 수립 (0) | 2024.03.25 |