[Java] 일정시간이 지나면 값이 없어지는(expiring) 맵, 캐시로 사용가능한 ExpiringMap
- IT/PROGRAMMING
- 2019. 2. 24. 19:13
자바 프로그래밍을 하다보면 콜렉션(collection) 중에 맵(Map)을 많이 사용하게 된다.
동시성(synchronization) 처리를 위하여 자바는 기본적으로 thread-safe한 java.util.concurrent.ConcurrentMap 객체를 제공한다.
또는 java.util.Collections.synchronizedMap()을 이용해도 된다.
그리고 복합키를 이용할 수 있도록 Apache에서 MultiKeyMap 객체도 제공한다.
Map에 키와 값을 계속해서 put하게되면 key만 중복되지 않으면 자꾸자꾸 들어가게 된다.
그 개수야 상당하게 크지만 그만큼 메모리 사용량은 늘어나게 된다.
필자도 spring-integration에서 이러한 현상을 발견하게 되었고 이를 해결하기 위하여, 일정시간이 지나면 Map에서 자동으로 제거되는 기능이 필요하였다.
물론 제거된 데이터는 더이상 필요없거나 다른 방법으로 다시 복구할 수 있는 상황이었다.
즉, 캐시와 유사한 기능을 가진 Map이 필요했다.
유사한 기능이 아니고, 그냥 캐시다.
캐시의 여러 정책중에 time-based 정책을 적용할 수 있는 Map이다.
ExpiringMap 이라는 라이브러를 찾게되었다.
2019년 2월 24일 기준, 최신버전은 0.5.9 이다.
소개페이지는 GitHub에 있다.
특징은 다음과 같다.
- High performance: 고성능이란다. 성능 테스트는 안해봤지만, 믿어야지!
- Low-overhead: Time-based이니깐 시간 계산을 할텐데, 연산이나 메모리 사용량이 많지 않은가 보다. 이것도 믿어야지!
- Zero dependency: 이건 진짜다. maven dependency가 없다.
- Thread-safe: 이야~ 멀티쓰레드 환경에서 동시성 문제도 해결해준다.
기본 maven repository에도 등록되어 있다.
- Apache Maven
<dependency>
<groupId>net.jodah</groupId>
<artifactId>expiringmap</artifactId>
<version>0.5.9</version>
</dependency>
- Gradle Groovy DSL
implementation 'net.jodah:expiringmap:0.5.9'
- Gradle Kotlin DSL
compile("net.jodah:expiringmap:0.5.9")
간단한 샘플 예제 몇가지를 살펴보겠다.
- 맵에 넣을 수 있는 최대 데이터는 1000개이고, 데이터를 입력한지 30초가 지나면 expire되는 맵이다.
- ExpirationPolicy.CREATED 정책대신에 ExpirationPolicy.ACCESSED 을 적용하면 마지막으로 get()한지 일정시간이 지나면 expire 된다. 즉, LRU(Least Recently Used) 정책을 적용할 수 있다.
// ExpiringMap 생성
Map<String, String> map = ExpiringMap.builder()
.maxSize(1000)
.expirationPolicy(ExpirationPolicy.CREATED)
.expiration(30, TimeUnit.SECONDS)
.build();
map.put("key-1", "value-1");
map.put("key-2", "value-2");
map.put("key-3", "value-3");
- 맵을 생성할 때 정책을 정하는 것이 아니라, 데이터를 put할 때 적용할 정책을 정할 수 있다. 심지어 각 데이터별로 정책을 다르게 적용할 수 있다.
// ExpiringMap 생성
ExpiringMap<String, String> map = ExpiringMap.builder()
.maxSize(1000)
.build();
map.put("key-1", "value-1", ExpirationPolicy.CREATED, 30, TimeUnit.SECONDS);
map.put("key-2", "value-2", ExpirationPolicy.ACCESSED, 2, TimeUnit.MINUTES);
jar 파일을 까보면 pom.xml 파일까지 포함해서 총 11개 파일이다.
대부분 간단한 정의나 짧은 소스들이며, ExpiringMap 클래스를 구현한 소느는 1000줄이 넘은 다소 긴 소스이다.
필자는 그냥 믿고 잘 쓰고 있어서 ExpringMap.java 소스를 분석하진 않았지만, 이 글을 작성하다 보니 궁금해지긴한다.
맵에 데이터가 입력될 때와 expiring될 때, 원하는 로직을 작성할 수 있는 리스너도 존재한다.
자세한 기능은 GitHub 페이지를 쭉~ 살펴보면 쉽게 파악할 수 있다.
또는 IDE에서 .(점) 입력하면 리스팅되는 메서드들로 쉽게 알 수 있다.
그만큼 쉽게 이용할 수 있다.
'IT > PROGRAMMING' 카테고리의 다른 글
[Spring] Hibernate에서 "Could not build ClassFile" 발생하는 오류 해결 (0) | 2019.03.10 |
---|---|
[Spring] spring-boot 1.5.X 부터 spring-kafka 사용할 수가 있네요. (0) | 2019.03.06 |
[Java] Iterable을 stream으로 처리하기 (0) | 2019.02.20 |
[Spring] spring-boot 버전 1.X와 2.X에서 Page 객체를 ObjectMapper(Jackson) 사용시 차이점 (0) | 2019.02.19 |
[Spring] 웹어플리케이션의 Whitelabel 오류 페이지 비활성화 (0) | 2019.02.19 |