자주 바뀌는 값이 아닌데, 데이터베이스에 접근해서 가져오는데 시간이 걸려서 불편할 때가 있다. 이럴 때 간단하게 서버 단에서 캐시로 들고 있을 수 있다.
필요성
- 데이터 중 매번 실시간 데이터를 반드시 반영해야 하는 경우가 아닐 때
- 복잡한 쿼리라 가져오는 작업이 빠르지 않을 때
- 위와 같은 경우 캐시 라이브러리를 이용해서 관리하면 성능에 도움이 된다.
- 스프링의 어노테이션을 이용해서 쉽게 캐싱처리를 할 수 있다.
EHcache
- 자바 기반 캐시 오픈소스
- 기본 JVM메모리에 저장된다.
- 레디스처럼 별도의 서버 설치 없이 사용할 수 있어, 가볍게 사용하기 좋다.
- EHcache는 로컬캐시로서 특정 서버에 종속된다. → 따라서 멀티 서버 환경에서는 데이터 싱크가 필요하다.
- 장 : 데이터 접근이 빠르다.
- 단 : 동기화가 속도에 영향을 줄 수 있고, 데이터 유실 가능성이 있다.
초기 설정
- dependency추가
implementation "org.springframework.boot:spring-boot-starter-cache" implementation "org.ehcache:ehcache:3.8.0" implementation "javax.cache:cache-api:1.0.0"
- Application에 어노테이션 추가
-
@EnableCaching @EnableScheduling @SpringBootApplication public class CubeApplication { public static void main(String[] args) { SpringApplication.run(CubeApplication.class, args); } }
-
ehcache.xml 설정
https://www.ehcache.org/documentation/3.3/getting-started.html
- 하나의 캐시를 사용할 때마다 <cache>를 구현해야 한다.
<cache alias="optionLists"> <!-- 캐시의 이름을 지정 -->
<key-type>java.lang.Object</key-type> <!-- Cache 인스턴스에 저장될 캐시의 키의 FQCN을 지정. 기본 값은 java.lang.Object -->
<value-type>java.lang.Object</value-type> <!-- value-type 요소는 Cache 인스턴스에 저장된 값의 FQCN을 지정. 기본 값은 java.lang.Object -->
<expiry> <!-- 캐시 만료기간 -->
<ttl unit="hours">12</ttl> <!-- 12시간이 지나면 만료되도록 설정함 -->
<!-- unit : days, hours, minutes, seconds, millis, micros, nanos -->
</expiry>
<!-- 캐시가 생성되고 삭제되는 이벤트를 모니터링 하고 싶을 때의 설정 -->
<listeners>
<listener>
<class>com.kakaopay.cube.common.CacheEventLogger</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>UNORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
</listener>
</listeners>
<resources> <!-- 캐시 데이터의 저장 공간과 용량을 지정 -->
<heap unit="entries">2</heap> <!-- 2개의 캐시를 사용하도록 설정 -->
</resources>
</cache>
<resources>
- resources는 캐시 데이터의 저장 공간과 용량을 지정한다.
- <heap> : JVM 힙 메모리에 캐시 저장하도록 세팅
- <offheap> : JVM 힙 메모리 외부의 메모리에 캐시를 저장하도록 세팅
- 옵션
- unit="entries" : 개수 지정
- unit="MB" : 용량 지정
캐시의 개수나 용량을 늘리면
- 파라미터가 없으면 그냥 하나의 캐시에 하나만 저장하면 된다. → entries = 1
- 파라미터가 있으면 캐시 하나로 부족
- 캐시 개수나 용량을 늘리면 그거에 맞게 여러개의 파라미터에 대한 결과값이 저장된다.
이벤트 모니터링
- ehcache.xml에서 모니터링 설정을 했다면 아래 처럼 CacheEventLogger를 선언해서 사용할 수 있다 .
- 이때 CacheEventLogger는 <listeners> 내부 <class>로 설정된 위치에 있어야 한다.
@Slf4j
public class CacheEventLogger implements CacheEventListener<Object, Object> {
@Override
public void onEvent(CacheEvent<? extends Object, ? extends Object> cacheEvent) {
log.info("cache event logger message:::::: getKey: {} / getOldValue: {} / getNewValue:{}",
cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue());
}
}
캐싱 처리
- 캐싱 처리를 하고 싶은 메소드 위에 @Cacheable만 설정해주면 된다.
- 이때, @Cacheable(cacheNames=캐시이름)에서 캐시이름은 ehcache.xml에서 alias로 설정한 이름
- @Cacheable는 캐시 저장 및 조회를 위한 어노테이션으로 처음 호출 됐을 때는 메소드 내부를 실행하고, 두 번째 부터는 메소드 내부를 실행하지 않고 캐시에서 값을 가져온다.
@Cacheable(cacheNames = "optionLists")
public String getOptionLists() {
}
캐시 저장 및 제거 스케줄링
- @Scheduled 어노테이션을 이용해서 캐시를 저장하고 제거하는 메소드를 스케줄링 할 수 있다.
-
@Scheduled(cron = "0 50 7 * * *") public void deleteAllCache() { for (String cacheName : cacheManager.getCacheNames()) { Objects.requireNonNull(Objects.requireNonNull(cacheManager.getCache(cacheName))).clear(); } } @Scheduled(cron = "0 0 8 * * *") public void saveUserCountCache() { impalaAuProfileRepository.getTotalAu(format.format(new Date())); impalaAuProfileRepository.getTotalUser(format.format(new Date())); }
반응형
'서버 > SpringBoot' 카테고리의 다른 글
스프링부트가 다중 유저 요청을 처리하는 방법 (Thread Pool, Thread Safe) (0) | 2022.11.25 |
---|---|
[Spring/Kotlin] Entity는 data class로 구현하는게 좋을까? (0) | 2022.05.15 |
[kotlin] spring jpa에서 복합키를 사용하는 방법, @EmbeddedId, @IdClass (0) | 2022.05.10 |
[Spring] 하나의 build.gradle 파일로 여러 내부 프로젝트 빌드하기 (0) | 2022.03.31 |
@RequestBody로 지정한 객체에 꼭 기본 생성자가 필요할까? (com.fasterxml.jackson.databind.exc.InvalidDefinitionException) (2) | 2022.01.05 |