티스토리 뷰
음.. 회사에서 관리자 페이지가 있는데, 5초마다 회원수를 조회하는 페이지 입니다. 많은 사람들이 접속하고, 동일한 쿼리를 계속 호출하기 때문에 DB Connection pool 문제와 여러 비효율적인 문제가 나타났습니다. 이를 개선하기 위해, cache를 도입해봤습니다.
저는 오픈소스로 많은 사랑을 받고 있는 ehcache를 사용해봤습니다.
https://www.ehcache.org/documentation/
캐시를 사용하게 되면 Redis, Memcached를 먼저 생각하실 텐데.. 어디서 주워 들은 건 있어서. ㅠㅠ ehcache가 구현이 쉽고 빠르다는 이야기가 생각나서 선택했습니다.
캐시는 제 사례와 같이, 동일한 데이터를 반복적으로 조회했을 때 이미 만들어져 있는 결과물을 조회하여, 자원낭비를 줄이는 방법입니다.
개발환경은 Spring 4.3.8 + Maven입니다. 먼저 의존성 설정을 해줍니다!!
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.googlecode.ehcache-spring-annotations/ehcache-spring-annotations -->
<dependency>
<groupId>com.googlecode.ehcache-spring-annotations</groupId>
<artifactId>ehcache-spring-annotations</artifactId>
<version>1.2.0</version>
</dependency>
그리고 Configuration 설정
springboot를 사용한다면, spring-boot-starter-cache로 인해 캐시관련 설정이 간단해 집니다. 그렇기에 아래와 같이 CacheManager와 EhCacheManagerFactoryBean등의 bean 설정을 안해도 됩니다.
springboot ehcache 설정은 아래 갓 블로그로...
https://jojoldu.tistory.com/57
@Configuration
@EnableCaching
public class EhcacheConfig {
@Bean
public EhCacheManagerFactoryBean ehCache(){
EhCacheManagerFactoryBean factoryBean = new EhCacheManagerFactoryBean();
factoryBean.setConfigLocation(new ClassPathResource("/ehcache.xml"));
factoryBean.setShared(true);
return factoryBean;
}
@Bean
public CacheManager cacheManager(EhCacheManagerFactoryBean ehCache){
return new EhCacheCacheManager(ehCache.getObject());
}
}
그리고 ehcache.xml을 하나 만들어 줍니다. 자세한 설정은 저도 ...잘... 몰라서 밑에 URL로 돌리겠습니다.
http://www.ehcache.org/ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false">
<defaultCache
eternal="false"
maxElementsInMemory="50"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="3"
memoryStoreEvictionPolicy="LRU" />
<cache
name="055055"
eternal="false"
maxElementsInMemory="100"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="10"
memoryStoreEvictionPolicy="LRU" />
</ehcache>
위에는 default 설정이고 밑에는 사용할 캐시 설정입니다.
name : 캐시 이름
eternal : true 설정 시, timeout설정이 무효가 된다. 캐시에서 삭제가 안됨!!! 밑에 timeToldelSeconds, timeToLiveSeconds 설정이 무의미해진다는 말..
maxElementsInMemory : 메모리에 저장될 수 있는 객체 최대 개수
overflowToDisk : 메모리에 저장된 객체 수가, maxElementsInMemory에서 정한 수를 넘으면 디스크에 overflow된
객체들을 저장할지 말지??
diskPersistent : 재가동 할 때 디스크에 캐싱된 객체를 저장할지 말지??
timeToldelSeconds : 지정한 seconds 동안 사용되지 않으면, 캐시에서 삭제 된다. default는 0이다. 값이 0이면 만료 시간 지정안함
timeToLiveSeconds : 지정한 seconds가 지나면 캐시에서 자동으로 삭제 된다. default는 0이다. 값이 0이면 만료 시간 지정 안함
memoryStoreEvictionPolicy : 객체의 개수가 maxElementsInMemory에 근접할 때, 메모리에서 객체를 어떻게 제거할지
LRU, FIFO, LFU 등등.. 기본은 LRU
@Override
@Cacheable(value = "055055")
public AlarmResponse getAlarmMemberCount() throws ServiceException {
AlarmResponse response = memberDao.selectMember();
return response;
}
그리고 대략 이런식으로 사용하면 됩니다.
@Cacheable annotation에 value는 cache이름.
@Cacheable(value = "055055", key="#name") 주로 이렇게 많이 사용하는데.. key는 캐시의 고유한 키입니다.
@Override
@Cacheable(value = "055055", key="#name")
public AlarmResponse getAlarmMemberCount(String name) throws ServiceException {
AlarmResponse response = memberDao.selectMember(name);
return response;
}
위와 같이 사용한다면, name별로 캐시가 별도로 쌓이게 됩니다.
어노테이션 설명
@EnableCaching : 스프링 캐시 활성화
@Cacheable : 캐시 갱신
@CacheEvict : 캐시된 데이터 제거
그리고 Service를 호출하는 Controller에서 한번 얼마나 걸리는지 확인해보겠습니다.
public AlarmResponse getAlarmMemberCount() throws ServiceException {
long start = System.currentTimeMillis();
System.out.println("####ehCache is Running...");
AlarmResponse response = mainService.getAlarmMemberCount();
long end = System.currentTimeMillis();
System.out.println("시간측정"+" : " +Long.toString(end-start));
return response;
}
참고 사이트
https://sooin01.tistory.com/entry/Spring-ehcache-%EC%84%A4%EC%A0%95
https://sjh836.tistory.com/129
https://jojoldu.tistory.com/57
'jvm언어관련 > Spring(SpringBoot)' 카테고리의 다른 글
간단한 springboot error 처리 (0) | 2019.02.22 |
---|---|
[책]자바 기반의 마이크로서비스 이해와 아키텍처 구축하기 (0) | 2019.02.18 |
AsyncRestTemplate 사용하기 (0) | 2019.01.28 |
스프링의 DI(Dependency Injection) 이란? (0) | 2019.01.21 |
spring boot 로컬환경에서 https 사용하기 (0) | 2019.01.01 |
- Total
- Today
- Yesterday
- 싱글턴
- update set multiple
- 다중 업데이트
- 그레이들
- vue.js
- 이것이 자바다
- 슬랙 /
- java
- visual studio code
- 뱅크샐러드 유전자
- MSSQL
- update query multi row
- multiple row update
- update query mutiple row
- 슬랙
- springboot https
- 슬랙봇
- 뱅크샐러드
- 뱅셀 유전자
- update query set multiple
- 이펙티브자바
- SpringBoot
- Slack
- 업데이트 쿼리
- update query
- update set multi
- spring-boot-starter-data-redis
- 몽고DB 완벽가이드
- gradle
- effectivejava
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |