배경 버스 터미널 어플을 개발하던 도중 조회성 정보중 거의 변하지 않는 정보를 많은 사용자가 매번 조회하기 위해 RDB에 접근하다 보면 DB 서버의 리소스를 사용하고 디스크 I/O가 자주 발생하여 DB 부하가 늘어날 것이라고 생각하였습니다. 또한 RDB에 최대한 적게 접근하면서 빠른 조회 응답을 얻는 방법 중에 캐시(Cache)가 있다는 것을 알게 되었습니다. 그렇다면 여기서 말하는 캐시(Cache)가 무엇인지 알아보도록 하겠습니다. 이전 글에서 인메모리 데이터 베이스 중 하나인 redis를 이용하여 대용량 트래픽을 처리하기 위한 세션 구조에 대해 글을 쓴 적이 있습니다. redis는 인메모리 데이터 베이스이지만 캐시 서버와 같은 기능을 하기도 합니다. Cache(캐시)란 자주 시용하는 데이터 값을 미리 복사해 놓는 임시 장소를 가리킵니다. 캐시를 시스템 상으로 분류하면,
이 캐시들은 os 및 하드웨어에서 제공하는 캐시를 말합니다. 즉 시스템의 성능을 높이는 데 사용되는 것들입니다. 앞으로 말하는 캐시는 하드웨어가 아닌 서버의 기준으로 다음과 같이 분류할 수 있습니다. 로컬 캐시(Local Cache)
글로벌 캐시(Global Cache)
캐시를 적용하기에 적합한 데이터
버스 터미널 조회 정보와 같은 자주 조회되면서 거의 변하지 않는 정보는 어떤 캐시 전략을 적용해야 할까요?. 여러 서버를 사용 시에 서버 간 데이터를 동기화를 하면서, 모든 사용자가 동일한 데이터를 조회하기 위해서는 글로벌 캐시 전략을 적용하기로 했습니다. 글로벌 캐시을 적용하기 위한 데이터는 어떤 데이터가 적합할까요?.
1분 뒤에 날아가도 되는 데이터나 RDBMS에서 데이터를 가져와도 되지만 매우 자주 사용되면서 캐시에 없으면 DB에서 가져오면 되는 것들에 적용하면 큰 효과를 볼 수 있습니다. 히트율(Hit Rate) 매우 자주 사용되는 데이터를 사용하여 캐시에 요청한 데이터가 존재하는 경우를 캐시 히트(Hit)라고 합니다. 반대로 자주 사용되는 데이터가 캐시에 존재하지 않는 경우를 캐시 미스(Miss)라고 합니다. 캐싱이 성능에 많은 영향을 미치는 만큼 자주 사용되는 데이터가 캐시에 얼마나 존재하는지를 의미하는 캐시 히트율이 높을수록 캐싱 성능이 향상됩니다. 또한 자주 사용되는 데이터이지만 캐시를 초기화하여 캐시에 존재하지 않을 경우 캐시 미스(Miss)가 발생하기도 합니다. 자주 조회되며, 변하지 않는 정보일수록 캐시 히트율이 높아 캐싱 성능 향상에 큰 영향을 미칩니다. 캐시 히트율이 높다는 의미는 디스크 I/O가 적게 발생하는 만큼 데이터 베이스 접근하는 빈도가 줄어들어 데이터 베이스 서버의 리소스를 적게 사용하게 됩니다. 또한 캐싱 성능 향상뿐 아니라 서버의 리소스를 적게 사용하여 서버 전체 성능 향상에도 영향을 미칩니다. 하지만 캐시 크기를 40에서 50으로 늘릴 경우 히트율의 증가가 캐시 크기를 20에서 20으로 또는 30에서 40으로 늘릴 경우에 비해 적다는 것을 알 수 있습니다. 이는 캐시 크기의 비례하여 히트율이 증가하지 않다는 것을 보여줍니다. 캐시 히트율이 높다고 무조건 성능이 비례하여 증가하지 않기 때문에 알맞은 캐시 크기는 애플리케이션에 따라 달라지며 적정 수준에서 캐시 크기를 정하는 것이 좋습니다. 캐싱 적용을 위한 설정 글로벌 캐시 전략을 적용하기 위해서 인메모리 데이터 베이스이면서 캐싱 처리에 적합한 Redis을 적용해보겠습니다. Spring에서 redis를 이용하여 캐시 설정을 해보도록 하겠습니다. @EnableCaching 어노테이션 추가 - 스프링 부트 애플리케이션에게 캐시 사용하겠다는 의미로 추가
SpringCacheManager 설정 RedisConfig라는 별도의 파일을 생성하여 CacheManager 인터페이스를 구현하는 RedisCacheManager를 Bean으로 등록하여 사용한다.
캐시 등록 및 조회 - @Cacheable 버스 터미널 목록이 매우 자주 사용되며 거의 변경되지 않는 데이터이므로 캐시 등록
검색 시 입력한 key 값으로 캐시를 검색합니다. key값이 없는 경우 고정된 키값(고정된 문자열)으로도 캐시 조회가 가능합니다. CacheManager 등록 시 설정했던 TTL(Time-to-live)은 @Cacheable에 사용하는 글로벌 설정이므로, 별도의 만료시간 설정을 하고 싶다면 @Scheduled라는 어노테이션을 사용하여 매개변수가 없는 메서드에 적용 가능합니다. 버스 터미널 캐시를 조회하는 Controller
캐시 적용 전 버스 터미널 전체 조회 캐시를 적용하지 않고 전체 조회를 한 경우 270ms 캐시 적용 후 버스 터미널 전체 조회 적용 전과 비교하여 270ms -> 7ms로 매우 빨라진 것을 확인할 수 있습니다. 결론 버스 터미널 어플을 개발하면서 매우 자주 사용되며 거의 변경되지 않는 데이터의 경우 조회 시간과 DB 부하를 줄이며 어떻게 빠른 조회가 가능할지에 대해 고민해봤습니다. 버스 터미널 목록은 거의 변하지 않으며 매우 자주 사용되는 데이터이며 자료의 크기가 크지 않아, 캐시에 저장하기에 적합하다고 생각했습니다. 이에 redis를 이용한 캐싱을 적용하였습니다. 적용 결과 조회 응답 속도가 매우 빨라지는 성과를 얻었습니다. 대용량 트래픽을 고려해본다면 여러 대의 서버가 접근하는 글로벌 캐시를 이용하였기에 동기화하여 모든 사용자가 동일한 데이터를 조회할 수 있다고 생각합니다. 이외에도스프링에서 redis를 지원한다는 점에서 차이가 있었습니다. 스프링에서 지원을 한다는 점에서 개발 편의성과 지속성이 좋다고 할 수 있습니다. References자바 성능 튜닝 이야기 http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9788966260928 자바 성능 튜닝 이야기 - 교보문고 『자바 성능 튜닝 이야기』는 고성능 애플리케이션을 위해 고려 해야 할 복잡한 요소들을 하나하나 짚어 주는 책이다. 장애를 일으키는 반복적인 코딩 이슈부터 시스템 진단, 튜닝 방법에 이르� www.kyobobook.co.kr https://spring.io/projects/spring-data-redis Spring Data Redis Spring Data Redis, part of the larger Spring Data family, provides easy configuration and access to Redis from Spring applications. It offers both low-level and high-level abstractions for interacting with the store, freeing the user from infrastructural c spring.io https://docs.aws.amazon.com/ko_kr/AmazonElastiCache/latest/red-ug/Strategies.html 캐싱 전략 - Redis용 Amazon ElastiCache 이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오. docs.aws.amazon.com Project Github URL 버스 예매 프로젝트 github URL |