Spring boot caffeine cache 설정 약술
프로젝트 는 Spring boot 개발 을 사용 하여 캐 시 기능 을 사용 하여 데이터베이스 압력 을 줄 여야 합 니 다.주로 사용 빈도 가 높 고 업데이트 빈도 가 낮은 설정 데 이 터 를 캐 시 하 는 데 사 용 됩 니 다.공식 적 으로 추천 하 는 실현 인 Caffine 을 선택 하 세 요.
도입 의존
<properties>
<spring.boot.version>1.5.6.RELEASEspring.boot.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>${spring.boot.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
<groupId>com.github.ben-manes.caffeinegroupId>
<artifactId>caffeineartifactId>
dependency>
기본 키 생 성기 설정
spring 이 제공 하 는 기본 값 은
org.springframework.cache.interceptor.SimpleKeyGenerator
이 며,사용 방법의 매개 변수 만 key 를 생 성 합 니 다.매개 변수 가 사용자 정의 조회 대상 이 라면 hashCode 와 equals()방법 을 다시 쓰 는 것 에 주의 하 십시오.사용자 정의 KeyGenerator 설정
간단 한 KeyGenerator 를 구현 합 니 다.매개 변 수 는 사용자 정의 조회 대상 이 라면 toString()방법 을 다시 쓰 는 것 에 주의 하 십시오.
이루어지다
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.StringJoiner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.interceptor.KeyGenerator;
public class CustomKeyGenerator implements KeyGenerator {
private static final Logger logger = LoggerFactory.getLogger(CustomKeyGenerator.class);
@Override
public Object generate(Object target, Method method, Object... params) {
String className = method.getDeclaringClass().getName();
String methodName = method.getName();
String paramHash = String.valueOf(Arrays.toString(params).hashCode());
String cacheKey = new StringJoiner("_").add(className).add(methodName)
.add(paramHash).toString();
logger.debug("generate cache key : {}", cacheKey);
return cacheKey;
}
}
bean
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import cn.migu.pk.constant.CommonConstants;
@Configuration
public class CaffeineCacheConfig {
private static final Logger logger = LoggerFactory.getLogger(CaffeineCacheConfig.class);
@Bean(CacheConstants.CUSTOM_KEY_GENERATOR)
public KeyGenerator createMapperKeyGenerator() {
return new CustomKeyGenerator();
}
}
기본 CacheManager 설정
spring-boot-starter-cache
가방 에 서 는 기본 적 인 CacheManager 를 제공 하여 CaffineCheManager 를 실현 합 니 다.모든 캐 시가 같은 설정 을 사용 하 는 것 이 단점 입 니 다.properties 프로필
spring.cache.cache-names=cfgDataCache
spring.cache.caffeine.spec=maximumSize=500,refreshAfterWrite=120s,expireAfterWrite=600s
자바 설정 클래스
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.github.benmanes.caffeine.cache.CacheLoader;
@Configuration
public class CaffeineCacheConfig {
private static final Logger logger = LoggerFactory.getLogger(CaffeineCacheConfig.class);
@Bean
public CacheLoader<Object, Object> createCacheLoader() {
return new CacheLoader<Object, Object>() {
@Override
public Object load(Object key) throws Exception {
logger.debug("cacheLoader load : {}", key);
return null;
}
};
}
@Bean(CacheConstants.CUSTOM_KEY_GENERATOR)
public KeyGenerator createMapperKeyGenerator() {
return new CustomKeyGenerator();
}
}
refreshAfterWrite
정책 을 사 용 했 기 때문에com.github.benmanes.caffeine.cache.CacheLoader
bean 을 정의 해 야 합 니 다.CafeineCheManager 의 cacheLoader(CacheLoader)구성원 변 수 를 자동 으로 연결 합 니 다.상수 류
public final class CacheConstants {
/*
*
*/
public static final String CFG_DATA_CACHE = "cfgDataCache";
public static final String BIZ_DATA_CACHE = "bizDataCache";
/*
* KeyGenerator
*/
public static final String CUSTOM_KEY_GENERATOR = "customKeyGenerator";
}
사용자 정의 CacheManager 설정
Simple CacheManager 를 사용 하여 서로 다른 Cache 설정 을 사용 합 니 다.
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
@Configuration
public class CacheManagerConfig {
private static final Logger logger = LoggerFactory.getLogger(CacheManagerConfig.class);
@Bean
public CacheManager createCacheManager() {
logger.info("cache manager initialize ...");
LoadingCache<Object, Object> cfgDataCache = Caffeine.newBuilder()
.maximumSize(100)
.refreshAfterWrite(5, TimeUnit.MINUTES)
.build(key -> load(key));
LoadingCache<Object, Object> bizDataCache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(1, TimeUnit.HOURS)
.build(key -> load(key));
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(
new CaffeineCache(CacheConstants.CFG_DATA_CACHE, cfgDataCache),
new CaffeineCache(CacheConstants.BIZ_DATA_CACHE, bizDataCache)));
return cacheManager;
}
@Bean(CacheConstants.CUSTOM_KEY_GENERATOR)
public KeyGenerator createMapperKeyGenerator() {
return new CustomKeyGenerator();
}
private Object load(Object key) throws Exception {
logger.debug("cacheLoader load : {}", key);
return null;
}
}
회수 정책
이 사례 에서 주로
maximumSize
,refreshAfterWrite
,expireAfterWrite
세 가지 전략 을 설정 했다.이름 과 의 미 를 고려 하여maximumSize
는 공간 을 바탕 으로 하 는 것 이 고refreshAfterWrite
과expireAfterWrite
은 시간 을 바탕 으로 하 는 것 이다.refreshAfterWrite
:캐 시 를 불 러 올 때 한 스 레 드 에서 캐 시 를 계산 하고 다른 스 레 드 는 오래된 값 을 직접 가 져 옵 니 다.expireAfterWrite
:캐 시 를 불 러 올 때 해당 스 레 드 를 막 고'자 물 쇠 를 가 져 오고 캐 시 를 계산 하 며 자 물 쇠 를 방출 합 니 다'이 예 에서 설정 한 데이터 의 캐 시 는
refreshAfterWrite
정책 을 사용 하기에 더욱 적합 합 니 다.주해 용법
주해 예시
spring boot 입구 류 에
@EnableCaching
주 해 를 추가 합 니 다.해당 방법 에서 해당 하 는 캐 시 주 해 를 사용 합 니 다.예 를 들 어 본 프로젝트 의 설정 데이터 캐 시 사용
refreshAfterWrite
정책 및@Cacheable
주 해 를 사용 합 니 다.@Mapper
public interface SysConstantMapper {
@Cacheable(cacheNames = CacheConstants.CFG_DATA_CACHE,
keyGenerator = CacheConstants.CUSTOM_KEY_GENERATOR,
sync = true)
List<SysConstantDO> selectRecordsByQO(@Param("cond") SysConstantQO cond);
}
사용자 정의 캐 시 주석
주석 에 있 는 인자 가 많 고 복잡 해 보이면 캐 시 주 해 를 사용자 정의 할 수 있 습 니 다.예 를 들 어:
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
@Caching(
cacheable = {
@Cacheable(cacheNames = CacheConstants.CFG_DATA_CACHE,
keyGenerator = CacheConstants.CUSTOM_KEY_GENERATOR,
sync = true)
}
)
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface CfgDataCache {
}
@Mapper
public interface SysConstantMapper {
@CfgDataCache
List<SysConstantDO> selectRecordsByQO(@Param("cond") SysConstantQO cond);
}
속성 설명
sync 속성:
캐 시 를 불 러 올 때 하나의 스 레 드 로 데 이 터 를 계산 하고 다른 스 레 드 가 막 힐 수 있 습 니 다.cafeine 자체 에 도 유사 한 메커니즘 이 있 지만
sync
속성 을 사용 합 니 다.다른 스 레 드 는 cafeine 이 아 닌 spring 으로 막 힙 니 다.cafeine 의 차단 메커니즘 에서 모든 막 힌 스 레 드 는'자 물 쇠 를 가 져 오고 캐 시 를 계산 하 며 자 물 쇠 를 방출 합 니 다'와 유사 한 과정 을 반복 해 야 하기 때문에 spring 이 막 히 고 막 힌 스 레 드 는 계산 데이터 의 스 레 드 가 캐 시 를 마 친 후에 캐 시 에서 데 이 터 를 직접 가 져 옵 니 다.sync 속성 과 unless 속성 은 공용 할 수 없습니다.
Synchronize the invocation of the underlying method if several threads are attempting to load a value for the same key. The synchronization leads to a couple of limitations:
This is effectively a hint and the actual cache provider that you are using may not support it in a synchronized fashion. Check your provider documentation for more details on the actual semantics.
—— javadoc
unless 속성:
캐 시 를 거부 하 는 데 사 용 됩 니 다.캐 시 계산 이 끝 난 후에 판단 합 니 다.이 표현 식 을 만족 시 키 면 계산 결 과 는 캐 시 에 추가 되 지 않 습 니 다.예 를 들 어
unless = "#result == null"
계산 결과 가 비어 있 으 면 캐 시 를 넣 지 않 는 다 는 뜻 이다.보충 설명
레 퍼 런 스
1.spring-boot-features-caching-provider-caffeine
2.ben-manes-caffeine
3.미래의 캐 시 에서 깊이 복호화-cafeine
4.카페인 캐 시
5.다 중 스 레 드 높 은 동시 다발 장면 에서 자바 캐 시 문 제 를 어떻게 해결 합 니까?