라이브러리

Spring boot 에 caffeine cache 적용하기

탄생 2022. 6. 15. 12:31

● 개요

일정기간 변경되지 않는 데이터에 대해 잦은 호출로 인하여 서버 자원 낭비를 방지하고자 cache를 활용하고자 한다.


java cache 라이브러리

java cache에 활용되는 라이브러리를 살펴 보았다.

1. springboot cache
springboot에서 지원하는 cache로 auto cofingired되어 설정에 대한 부분이 편리하다.
(https://spring.io/guides/gs/caching/)

 

2. caffeine cache

캐시를 읽고 쓰는 속도에서 가장 좋은 성능을 보여주는 라이브러리로 설정도 편리하다.
속도 측정 참고- https://github.com/ben-manes/caffeine/wiki/Benchmarks

Read (100%) - 8개의 쓰레드를 동시에 읽습니다.
Read (75%) / Write (25%) - 6개의 스레드  는 최대 크기로 구성된 캐시 에서 동시에 읽고  2개의 스레드 는 캐시에 씁니다.

 

Write (100%) - 8개의 스레드  가 최대 크기로 구성된 캐시에 동시에 씁니다.

3. ehcache

cache 라이브러리중 가장 많은 기능을 지원한다. 서버 간 분산캐시, 동기/비동기,  디스크 저장 지원등

 

- 프로젝트를 단순 캐시 저장후 조회만 하면 되기 때문에 캐시의 성능면에서 뛰어난 caffeine cache를 적용하려고 한다.


caffeine cache 구현하기

1. dependency 추가

implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'com.github.ben-manes.caffeine:caffeine:3.1.1'

2. Spring cache management 활성화(@EnableCache)

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@EnableCaching	// 캐시 활성화
@SpringBootApplication
public class SpringbootCaffeineCacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootCaffeineCacheApplication.class, args);
    }

}

3. 캐시에 저장할 내용을 enum으로 정의

- enum이 아닌 직접 설정파일에 입력을 해도 되지만 많은 캐시저장소를 정의할 경우 enum을 활용하여 관리하는것이 편리합니다.
- 만료시간이 0이라면 만료되지 않습니다.

- 최대갯수의 경우 모두 입력하게 되면 첫번째로 돌아가 첫번째 값을 제거하고 쓰여진다.

@Getter
@AllArgsConstructor
public enum CacheType {
    CACHE_STORE("cacheStore", 5 * 60, 10000);

    private final String cacheName;     // 캐시 이름
    private final int expireAfterWrite; // 만료시간
    private final int maximumSize;      // 최대 갯수
}

4. config bean  등록

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import net.suby.springbootcaffeinecache.caffeine.enums.CacheType;

import com.github.benmanes.caffeine.cache.Caffeine;

@Configuration
public class CacheConfig {

    @Bean
    public List<CaffeineCache> caffeineConfig() {
        return Arrays.stream(CacheType.values())
                     .map(cache -> new CaffeineCache(cache.getCacheName(), Caffeine.newBuilder()
                                                                                   .recordStats()
                                                                                   .expireAfterWrite(cache.getExpireAfterWrite(),
                                                                                                     TimeUnit.SECONDS)
                                                                                   .maximumSize(cache.getMaximumSize())
                                                                                   .build()
                          )
                     )
                     .toList();
    }

    @Bean
    public CacheManager cacheManager(List<CaffeineCache> caffeineCaches) {
        final SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(caffeineCaches);
        return cacheManager;
    }
}

5. cache 적용

- @Cacheable 를 사용하여 결과값을 캐시에 저장하며 캐시에 동일한 키가 있다면 캐시에 저장된 값을 리턴합니다.

- cacheNames : caffeineCache에 저장한 캐시명

- key : 캐시에 등록되는 키로 동일한 key값이 입력되면 캐시의 값을 바로 리턴합니다.

만약 파라미터가 여러개라면 연결을 하거나 toString으로 정의하여 key값을 정의하여 줍니다.

import static java.lang.Thread.sleep;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

@Service
public class CaffeineCacheService {

    @Cacheable(cacheNames = "cacheStore", key = "#name")
    public String getCache(String name) throws InterruptedException {
        sleep(3000);
        return name;
    }
}

6. cache 제거

- @CacheEvict 를 사용하여 캐싱에 저장된 키값을 제거합니다.

- value : 캐시명

- key : 캐시가 저장된 키값

import static java.lang.Thread.sleep;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

@Service
public class CaffeineCacheService {
    @CacheEvict(value = "cacheStore", key = "#name")
    public String removeCache(String name) {
        return "OK";
    }
}

● git 주소

https://bitbucket.org/technology-team/springboot-caffeine-cache/src/master/


● 참고 url
https://halkrine.tistory.com/64
https://velog.io/@soongjamm/Caffeine-Cache-%EB%A5%BC-%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%B8-%EA%B2%BD%ED%97%98
https://wave1994.tistory.com/182
https://ykh6242.tistory.com/entry/Spring-Cache-Abstraction-%EC%A0%95%EB%A6%AC
https://gosunaina.medium.com/cache-redis-ehcache-or-caffeine-45b383ae85ee
https://blog.yevgnenll.me/posts/spring-boot-with-caffeine-cache