// 인기 카드 Top3 조회 ( Redis )
@Transactional(readOnly = true)
public Map<String, Integer> getTopViewCardList() {
Set<ZSetOperations.TypedTuple<Object>> topCardsWithScores =
redisTemplate.opsForZSet().reverseRangeWithScores(TODAY_RANKING_KEY, 0, 2);
return topCardsWithScores.stream()
.collect(Collectors.toMap(
tuple -> tuple.getValue().toString(), // title
tuple -> tuple.getScore().intValue() // 조회수 ( score )
));
}
카드를 단건 조회하면 조회한 수 만큼 count 가 늘고, 그 count 에 따라 일일 Top3 조회 카드 제목을 조회하는 메서드를 구현했다.
해당 메서드는 이미 redis 서버에 저장되어있는 데이터들만 다루기 때문에 캐시에서만 데이터를 가져오는 케이스이다.
필자는 여기서
userService.findUser(userId);
user 정보가 데이터베이스에 저장되어있나 확인을 하는 코드를 추가해서 데이터베이스에 고의로 접근을 시켰고,
두 케이스를 비교하기를 원했다.
1. DB 에 접근을 한 경우 ( 898 ms )
2. DB 에 접근을 아예 안 한 경우 ( 778 ms )
조회 방법 | DB 접근 | DB 접근 X |
속도 ( ms ) | 898 | 778 |
데이터베이스를 접근했던 것 보다 고작 15% 성능이 향상되었다.
생각보다 성능 향상이 눈에 띄지 않아 실망했고 몇 가지 이유를 찾아보았다.
왜 별로 차이 안 나 ?
1. DB 조회 쿼리의 비용이 매우 낮은 경우
우선 위에 findUser 메서드는 userRepository 의 findById JPA 메서드로 이루어져있는데, 이는 Index 방식으로 데이터를 조회해온다.
Index 방식으로 데이터를 조회하고, 단건 조회 방식이고, 애초에 데이터베이스에 User 데이터가 많이 없기 때문이 차이가 미미했다고 본다.
2. 트랜잭션 오버헤드가 미미한 경우
트랜잭션 오버헤드가 뭘까? 트랜잭션 오버헤드란 트랜잭션이 발생할 때 드는 추가적인 비용을 뜻한다.
트랜잭션은 데이터베이스에 데이터를 주고 받을 때 일관성과 안전성을 제공하지만 이 과정에서 시간과 자원이 더 사용된다.
이게 트랜잭션 오버헤드다.
[ 트랜잭션 오버헤드에 대한 자세한 정보는 아래 게시물을 확인 ]
https://hanstory33.tistory.com/236
하지만 내 코드에서는 단순 조회하는 메서드이기 때문에 트랜잭션에 (readOnly = true) 옵션을 넣어줬다.
flush 자체를 안하기 때문에 트랜잭션이 사용되더라도 최소화할 수 있다.
그럼 쓰래드 값을 늘려보자 !
단건 조회에서 차이가 미미했으니, 요청 쓰래드 값을 늘려서 많은 사용자들이 요청을 보내는 경우로 가정해서 차이를 보고자 했다.
JMETER 툴을 사용해서 테스트했다.
User Thread Count 10,000
Warm up time 10
Loop count 1
위와 같이 세팅을 해주고 두 케이스를 비교해봤다.
1. DB 에 접근을 한 경우 ( 2166 ms - 95 % 기준 )
2. DB 에 접근하지 않는 경우 ( 741 ms - 95 % 기준 )
조회 방법 | DB 조회 | DB 조회 X |
속도 ( ms ) | 741 | 2166 |
약 66 % 성능이 향상되었다.
결론
DB 에 접근을 하는 경우와 아예 접근하지 않는 경우의 성능 비교를 해 보았는데,
DB 조회 쿼리 비용이 매우 낮고 , 오버헤드가 미미했던 이유 때문에 예상보다 차이가 미미했다. ( 15 % 향상 )
그래서 더 많은 트래픽을 날려서 차이를 확인해보자 했고 10000 개의 트래픽을 날려서 확인해본 결과 유의미한 결과 차이가 나왔다. ( 66 % )
'컴퓨터 프로그래밍 > Redis' 카테고리의 다른 글
[Redis] SpringBoot 에 Redis 초기 세팅 코드 (0) | 2024.10.16 |
---|