캐시 유형
- 캐시
- 한 번 읽은 데이터를 일정 공간에 저장, 같은 데이터를 또 다시 요청할 때 바로 보내주는 기술
- 버퍼와 달리 데이터를 투명하게 저장함
- 투명성 - 클라이언트에서 데이터에 이르기까지 한 눈에 보이는 것
- 버퍼
- 캐시와 유사히 데이터를 임시로 저장해 두는 역할
- 캐시히트
- 클라이언트가 요청한 내용과 캐시에 저장된 내용이 같은 경우
위치에 따라
- 웹 영역
- 웹 영역에 해당하는 솔루션들은 코드와 무관하게 별도의 서버를 설치한 후 사용, 데이터가 서버에 저장되며 캐시에 데이터를 저장하는 것과 무관
- 데이터 영역
- 데이터 영역에 해당하는 솔루션들은 데이터를 저장하거나 조회하는 코드들과 밀접한 연관이 있음
- 사용자 PC 영역
유형에 따라
데이터 영역에 해당하는 솔루션들 구분
- 로컬 캐시
- 별도의 서버 설치 없이 사용 가능
- 모든 데ㅐ이터를 이를 이용하여 저장하게 되면
- 힙 메모리가 기하급수적으로 증가 -> 가비지 컬렉터 청소 시간 증가 -> 성능 저하
- Ex) Ecache
- 분산 캐시
- 별도의 장비에 서버를 설치해야 사용 가능
- 로컬 메모리를 크게 잡을 필요가 없음
- 네트워크를 통해 분산 캐시를 사용
스프링 캐시
- 스프링 context 모듈에 캐시 관련 내용들이 있음
- 별도의 모듈 추가 필요 X
스프링 캐시 설정
- 별도의 모듈 추가 필요 X
- 캐시 객체들은 캐시 매니저에 저장되고 관리
@Bean public CacheManager cacheManager(){ SimpleCacheManager cacheManager = new SimpleCacheManager(); Cache myCache = new ConcurrentMapCache("carName"); cacheManager.setCaches(Arrays.asList(myCache)); return cacheManager; }
-
ConcurrentMapCache
- “carName”은 사용자가 지정할 수 있는 값
- 서비스 메서드에서 캐시 사용 시 지정하는 어노테이션의 이름값
- “carName”은 사용자가 지정할 수 있는 값
-
@EnableCaching
- 캐시를 사용할 수 있도록 함
서비스 메서드에 캐시 적용
@Cacheable(cacheNames = "carName")
public Car getByName(String name) {
makeSlowService();
Car myCar = new Car(name);
return randomCarColor(myCar);
}
-
@Cacheable
- 캐시 결과를 보여 줄 때 사용
- CacheNames와 key가 있음
- key는 해당 캐시 객체 안에서 식별할 수 있는 키 값
캐시 매니저에서 조회
public Car getByNameWithCachManager(String name) {
Cache cache = cacheManager.getCache("carName");
return randomCarColor(cache.get(name, Car.class));
}
-
getCache
- 파라미터를 입력하여 캐시 객체를 얻는 메소드
-
cache.get()
- 리턴 타입은 ValueWrapper
- 두 번째 인자에 클래스 명을 같이 기입
Jcache
- Jcache
- 자바 표준 캐싱 API
- 어플리케이션이 메모리 내에 캐시 객체를 만들고 작업할 수 있는 API 제공
- Oracle Coherence, Ecache, 등과 같은 자바를 지원하는 캐시 솔루션들이 Jache 스펙을 바탕으로 구현되어 있음
Jcache 구조
- CachingProcider와 CacheManager의 두 인터페이스를 가지고 있음
- CacheManager를 통해 캐시 객체를 얻음
- Entry는 key, value를 가지는 Map
Jcache 설정
의존성 추가
compile group: 'org.ehcache', name: 'jcache', version: '1.0.1'
compile group: 'javax.cache', name: 'cache-api', version: '1.0.0'
Jacache 객체 생성 및 실행
- cache provider와 cache manager를 얻는 방법
CachingProvider cachingProvider = Caching.getCachingProvider(); CacheManager cacheManager = Caching.getCachingManager();
- 캐시 생성시 정책이 필요함
- 이는 MutableConfiguration 클래스르 사용해서 설정 가능
-
setTypes
- cache 객체에 데이터를 저장할 때 타입
-
setStoreByValue
- 데이터 저장 시 값 또는 참조를 저장할 것인지에 대한 옵션
-
setExpiryPolicyFactory
- 캐시 만료일 설정
MutableConfiguration<Long, String> config = new MutableConfiguration<Long, String>() .setTypes(Long.class, String.class) .setStoreByValue(false) .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE));
- 캐시 만료일 설정
- 캐시 생성
- 캐시 생성 시 첫 번째 파라미터는 캐시명이다.
- 두 번째 파라미터는 설정
- 위에서 정책을 설정하고 해당 정책을 넘긴다.
Ehcache
- JCache에서는 캐시 저장을 map으로 함
- Ecache는 캐시 내용을 디스크에 저장할 수 있음
- 설정을 통해서 캐싱에 관련된 다양한 옵션들을 적용할 수도 있음
Ehcache 설정
- 의존성 추가
compile group: 'net.sf.ehcache', name: 'ehcache', version: '2.10.4'
- Ehcahce 설정을 위한 xml 파일
- ehcache 태그를 루트로 하위에 cache 태그들을 삽입할 수 있음
- cache 태그들은 name으로 구분
- ehcache 설정 시 maxEntriesLocalHeap 또는 maxBytesLocalHeap 둘 중 하나는 설정해야 함
- 이는 메모리에 생성될 객체의 최대 수이다. ```xml <?xml version=”1.0” encoding=”UTF-8”?>
## Ehcache 사용
### method 캐시 적용
- `@Cacheable`
- ehcache.xml파일에 설정한 name 값으로 파라미터를 넘겨준다.
- ehcahce에서는 `@CacheResult` 대신 `@Cacheable`을 사용
## 커스텀 키 생성 및 적용
### 기본키 생성기
- 캐시 사용 시 기본적으로 DefaultKeyGenerator가 사용됨
- 메서드의 파라미터가 캐시 저장소의 키로 저장됨
- 위 문제로 여러 메서드에서 공통으로 사용하려고 하면 서로 다른 키값으로 지정해야 함 (이름이 달라야 함)
- 메서드별로 고유한 키 생성하도록 만들면 메서드별로 캐시를 사용할 수 있음(이름이 같더라도)
### 키 생성기 구현
- CachingConfigurerSupport클래스를 상속받고 keyGenerator 메서드를 오버라이딩 함
```java
@EnableCaching
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
StringBuilder sb = new StringBuilder();
sb.append(o.getClass().getName());
sb.append(method.getName());
for (Object obj : objects) {
sb.append(obj.toString());
}
return sb.toString().hashCode();
}
};
}
}