결혼식 일정에 가까워질수록 하객들은 링크로 전달된 모바일 청첩장을 조회한다.
이때 동일한 ID로 동일한 응답을 기대하는 요청이 많아진다.
현재는 같은 청첩장의 ID에 대해 서버는 매번 데이터베이스에서 조회를 하고 응답값을 만들어 제공
한다.
최근 조회한 청첩장 ID는 데이터베이스와 통신하지 않고 캐시를 통해 응답을 제공하면
사용자에게 더 빠른 응답, Database와의 네트워크 자원을 아낄 수 있다.
@Bean
public CacheManager cacheManager(RedisConnectionFactory cf) {
PolymorphicTypeValidator typeValidator = BasicPolymorphicTypeValidator.builder()
.allowIfSubType(Object.class)
.build();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.activateDefaultTyping(typeValidator, ObjectMapper.DefaultTyping.NON_FINAL);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper)))
.entryTtl(Duration.ofDays(3L));
return RedisCacheManager.RedisCacheManagerBuilder
.fromConnectionFactory(cf)
.cacheDefaults(redisCacheConfiguration)
.build();
}
Cache는 Redis를 사용했다.
3일 전 부터 하객들로부터 요청 수가 많아질 것으로 예상되어 TTL을 3일로 설정하였다.
Spring은 @Cacheable 어노테이션을 지원해줘서
@Transactional(readOnly = true)
@Cacheable(value = "Products", key = "#tsid", cacheManager = "cacheManager")
public LinkedHashMap<String, Object> read(Long tsid) {
}
와 같이 AOP로 캐시를 쉽게 구현할 수 있다.
다만 수정 / 삭제가 발생 했을 때, 데이터 정합성에 유의해야한다.
데이터베이스에 수정/ 삭제가 반영되어도 캐시에 청첩장 조회 응답이 여전히 저장되어 있다면
청첩장 조회 요청이 들어왔을 때 캐시에 값이 남아 있어 수정 / 삭제되기 전 청첩장 조회 응답이 나가 데이터가 일치하지 않는 문제가 발생한다.
그렇기 때문에 수정이나 삭제 시,
@CacheEvict(value = "Products", key = "#tsid", cacheManager = "cacheManager")
와 같은 어노테이션으로 삭제를 해주어야한다.