Caffeine Cache
MS-SQL
MongoDB
회사에서 DB 부하를 감소시키고, 응답속도를 개선하기 위해 로컬 캐시를 사용중이다. 캐시를 그냥 생각없이 사용할 때는 “캐시하니까 어떤 쿼리를 날려도 상관 없지 않을까?”라는 안일한 생각을 했었다.
동시성을 공부하다가 문득, 캐시가 삭제되고, 캐시를 갱신하는 시점에 동시에 요청이 몰려 들어오게되면 어떻게 될까? 그런데 하필 쿼리가 슬로우 쿼리라서 시간이 오래 걸린다면 어떤 영향이 있을까? 라는 궁금증이 생겼다.
로컬 캐시의 작용 기전은 다음과 같다
캐시가 있는지 확인한다
→ 캐시가 있으면 캐시 결과를 반환한다
캐시가 없을 경우, 메서드 내 로직을 수행한다
메서드 내 로직이 완료되고, 결과가 리턴되면 캐시가 완료된다
위 내용을 토대로, 아래의 가정을 해보았다.
실험을 수행했다
// 캐시 갱신 메서드
@Cacheable(cacheNames = "Post", key = "'all'", cacheManager = "defaultCacheManager")
public List<Post> getPosts(LocalDateTime localDateTime) throws InterruptedException {
log.info("[{}] getPosts 호출", Thread.currentThread().getName());
List<Post> result = postRepository.findAll(); // 쿼리
Thread.sleep(4000); // 4초간 대기
log.info("[{}] query 결과 획득", Thread.currentThread().getName());
return result;
}
// 캐시 테스트
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CacheTest {
@LocalServerPort
private int port;
private RestTemplate restTemplate;
@BeforeEach
void setUp() {
restTemplate = new RestTemplateBuilder()
.rootUri("<http://localhost>:" + port)
.build();
}
@Test
void name() {
try (ExecutorService threadPool = Executors.newFixedThreadPool(10)) {
for (int i = 0; i < 10; i++) { // 스레드 풀을 이용해 10회 요청
threadPool.submit(() -> {
restTemplate.getForEntity("/posts", String.class);
});
}
}
}
}
내 가정대로라면, 쿼리가 갱신되는 4초간 들어오는 요청은 모두 캐시를 이용하지 못하고 쿼리가 날아갈 것이다.