강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của brian1103269537
brian1103269537

câu hỏi đã được viết

Nhập môn và Thực hành Redis dành cho cả người không chuyên (Phần tối ưu hóa hiệu suất truy vấn)

Redis를 적용했음에도 불구하고 조회 성능의 큰 차이가 없고 오히려 더 안좋은 조회속도를 보이는 것 같습니다.

Viết

·

130

·

Đã chỉnh sửa

0

간단한 영화 목록 조회입니다. 총 약 10000개의 데이터가 있습니다. redis를 적용하고 조회성능이 좋아진것은 맞지만 이상하게 redis를 적용하기 전에도 같은 조회를 계속해도 조회속도가 똑같이 빨라지는 현상을 겪고있습니다. 현재 이 movie는 MSA 의 여러 서비스 중 하나입니다. 혹시 MSA 아키텍쳐 자체가 문제가 될 수도 있나요?

@Cacheable(cacheNames = "getMovies", key = "'movie:all'",
        cacheManager = "movieCacheManager")
public List<Movie> getAllMovies() {
    return movieRepository.findAll();
}


@GetMapping("/movies")
    public ResponseEntity<List<MovieDto>> getAllMovies() {
        List<Movie> allMovies = movieService.getAllMovies();
        List<MovieDto> dtos = new ArrayList<>();
        for (Movie movie : allMovies) {
            dtos.add(new ModelMapper().map(movie, MovieDto.class));
        }

        return ResponseEntity.status(HttpStatus.OK).body(dtos);
    }


@Configuration
@EnableCaching // Spring Boot의 캐싱 설정을 활성화
public class RedisCacheConfig {

    @Bean
    public CacheManager movieCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
                .defaultCacheConfig()
                // Redis에 Key를 저장할 때 String으로 직렬화(변환)해서 저장
                .serializeKeysWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(
                                new StringRedisSerializer()))
                // Redis에 Value를 저장할 때 Json으로 직렬화(변환)해서 저장
                .serializeValuesWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(
                                new GenericJackson2JsonRedisSerializer()
                        )
                )
                // 데이터의 만료기간(TTL) 설정(1분)
                .entryTtl(Duration.ofMinutes(1L));
        return RedisCacheManager
                .RedisCacheManagerBuilder
                .fromConnectionFactory(redisConnectionFactory)
                .cacheDefaults(redisCacheConfiguration)
                .build();
    }

}

@Configuration
public class RedisConfig {

    @Value("${spring.data.redis.host}")
    private String host;

    @Value("${spring.data.redis.port}")
    private int port;

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(new RedisStandaloneConfiguration(host, port));
    }

}
redisnosqlquery-tuningperformance-tuning

Câu trả lời 3

0

jscode님의 프로필 이미지
jscode
Người chia sẻ kiến thức

안녕하세요 ! 질문 잘 해주셨어요 !

질문해 주신 내용에 대해 상황을 기반으로 하나씩 정리해서 답변드려 볼게요 !

 

[1] JPA 자체의 1차 캐시(영속성 컨텍스트) 때문일 가능성

우선 가장 유력한 원인이라고 생각됩니다 !

"movieRepository.findAll()이 반복 호출임에도 DB 부하 없이 빠른 이유"

Spring Data JPA는 기본적으로 영속성 컨텍스트(EntityManager)가 존재하며,

트랜잭션 안에서 같은 데이터를 여러 번 조회할 경우 DB를 다시 조회하지 않고

1차 캐시에 보관된 엔티티를 반환해요~

즉, Redis를 사용하지 않아도 같은 요청이 계속 반복된다면,

이미 JPA가 빠른 결과를 리턴해줬던 것일 수 있어요!

 

[2] 너무 많은 10,000개 영화 데이터를 한번에 캐싱

@Cacheable은 조회 결과 전체를 메모리에 캐싱해요 ~

10,000개 Movie 객체를 JSON 직렬화하여 저장/읽기하는 건 Redis I/O 비용이 크며,

이걸 네트워크 통해 주고받는 것도 성능 이슈가 될 수 있어요!

즉, 무작정 큰 데이터를 한 번에 캐싱하는 건 오히려 역효과가 발생할수 있어요 !

 

"MSA 아키텍처 자체가 원인이 될 수 있을까요?"

-> 직접적인 원인은 아니라고 생각해요 ~

위 두 부분을 확인한뒤 해당 사항을 고려해보는 것을 추천드려요 !

 

추가로 궁금한 사항 있으시면 언제든 질문 남겨주세요~~ 😄

brian1103269537님의 프로필 이미지
brian1103269537
Người đặt câu hỏi

먼저 일단 문제는 해결되었습니다! 10000건의 데이터를 100만개의 데이터로 개수를 늘렸고 조회를 100만개를 다 하는것이 아니라 페이징을 적용했더니 큰 차이가 있었습니다. 실제로 Redis 적용전 475ms -> 90ms였는데 Redis 적용 후 600ms->9ms로 큰 성능을 맛볼 수 있었습니다. 감사합니다!

0

안녕하세요, 인프런 AI 인턴입니다. 이수현님께서 Redis 적용 후 성능 저하와 관련하여 질문을 주셨네요. 캐시 적용 후 성능이 개선되지 않는 원인은 여러 가지가 있을 수 있습니다. 몇 가지 가능한 원인과 해결 방안을 제안드리겠습니다.

1. 캐시 미스(Cache Miss)

Redis에 캐시된 데이터가 없는 경우, 캐시 미스로 인해 DB에 다시 접근하여 데이터를 가져오는 데 시간이 소비됩니다. 처음 한 번은 캐시 미스가 발생할 수 있지만, 그 이후로는 캐시에 데이터가 저장되어야 합니다. 실제로 후속 요청에서도 성능 문제가 유지되는지 확인해보세요.

2. Redis 설정 확인

  • Redis의 메모리 사용량이나 저장 가능 용량이 부족하다면, 캐시된 데이터를 유지하지 못하고 만료될 수도 있습니다.
  • Redis 설정 파일이나 메모리 정책을 확인하고 필요한 만큼 자원을 할당했는지 확인하세요.

3. 네트워크 딜레이

애플리케이션 서버와 Redis 서버 간에 네트워크 딜레이가 있으면 성능 저하를 유발할 수 있습니다. 같은 네트워크 환경에서 테스트하거나 네트워크 속도를 측정해볼 필요가 있습니다.

4. 객체 직렬화/역직렬화

  • GenericJackson2JsonRedisSerializer를 사용하셨는데, 데이터 변환 과정에서 성능에 영향을 미칠 수 있습니다. Jackson2JsonRedisSerializer로 변경해서 테스트를 시도해보세요.
  • 대량의 데이터 변환이 필요한 경우, 객체 직렬화에 따른 오버헤드가 발생할 수 있습니다.

5. 방대한 초기 로드

처음부터 모든 데이터를 캐시에 로드하는 방식(findAll())은 대량의 데이터를 불러오면서 성능 저하를 발생시킬 수 있습니다. 페이징을 통해 데이터를 부분적으로 로드하는 방법을 고려해 볼 수 있습니다.

유사 질문 및 추가 자료

아래 유사 질문에서 해결의 실마리를 찾으실 수도 있습니다:
- 캐싱 객체 직렬화/역직렬화

이해에 도움이 되셨기를 바랍니다. 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.

현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

0

brian1103269537님의 프로필 이미지
brian1103269537
Người đặt câu hỏi

추가적인 Movie와 MovieDto 코드입니다.

@Data
public class MovieDto {

    private Long id;
    private String title;
    private String genre;
    private Integer runningTime;
    private String descreption;
    private String director;

    @JsonFormat(pattern = "yyyy-MM-dd")
    @JsonSerialize(using = LocalDateSerializer.class)
    @JsonDeserialize(using = LocalDateDeserializer.class)
    private LocalDate releaseDate;

}

@Data
@Entity
public class Movie {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;
    private String genre;
    private Integer runningTime;
    private String descreption;
    private String director;

    @JsonFormat(pattern = "yyyy-MM-dd")
    @JsonSerialize(using = LocalDateSerializer.class)
    @JsonDeserialize(using = LocalDateDeserializer.class)
    private LocalDate releaseDate;

}
Hình ảnh hồ sơ của brian1103269537
brian1103269537

câu hỏi đã được viết

Đặt câu hỏi