2013년 3월 25일 월요일

Spring 3.1 + Couchbase 를 이용하여 Cache 만들기

오늘 글 쓴 김에 다 써버려야 겠네요...
이번에는 Couchbase 를 저장소로 사용하여, Spring Cache 를 사용해 보도록 하겠습니다.
간략하게 Couchbase 에 대해 설명하면... Memcached + CouchDB 라고 보시면 되구요. 설정에 따라 메모리 저장소로 (Memcached), Document DB 형태(CouchDB) 로 사용할 수 있습니다.
Memcached 의 단순 캐시에서 DocumentDB 로 발전했다고 보시면 되고, Map Reduce 도 가능합니다.

하지만!!! 오늘은 그냥 캐시로 사용하려고 합니다.

1. CouchbaseCacheManager

@Slf4j
public class CouchbaseCacheManager extends AbstractTransactionSupportingCacheManager {
private CouchbaseClient couchbaseClient;
@Getter
@Setter
private int expireMillis = 0; // 0 : persist forever
public CouchbaseCacheManager(CouchbaseClient couchbaseClient) {
this(couchbaseClient, 0);
}
public CouchbaseCacheManager(CouchbaseClient couchbaseClient, int expireMillis) {
Guard.shouldNotBeNull(couchbaseClient, "couchbaseClient");
this.couchbaseClient = couchbaseClient;
this.expireMillis = expireMillis;
}
@Override
protected Collection<? extends Cache> loadCaches() {
Collection<Cache> caches = Lists.newArrayList();
for (String name : getCacheNames()) {
caches.add(new CouchbaseCache(name, couchbaseClient, expireMillis));
}
return caches;
}
@Override
public Cache getCache(String name) {
synchronized (this) {
Cache cache = super.getCache(name);
if (cache == null) {
cache = new CouchbaseCache(name, couchbaseClient, expireMillis);
addCache(cache);
}
return cache;
}
}
}


2. CouchbaseCache

@Slf4j
public class CouchbaseCache implements org.springframework.cache.Cache {
@Getter
private String name;
@Getter
private CouchbaseClient nativeCache = null;
@Getter
@Setter
private int expireMillis = 0; // msec (0 is persist forever)
public CouchbaseCache(String name, CouchbaseClient client, int expireMillis) {
Guard.shouldNotBeNull(name, "name");
Guard.shouldNotBeNull(client, "client");
this.name = name;
this.nativeCache = client;
this.expireMillis = expireMillis;
if (log.isDebugEnabled())
log.debug("CouchbaseCache 를 생성합니다. name=[{}], nativeCache=[{}]", name, nativeCache);
}
private String getKey(Object key) {
return name + "|+|" + key;
}
@Override
public ValueWrapper get(Object key) {
Guard.shouldNotBeNull(key, "key");
Object result = nativeCache.get(getKey(key));
SimpleValueWrapper wrapper = null;
if (result != null)
wrapper = new SimpleValueWrapper(result);
return wrapper;
}
@Override
public void put(Object key, Object value) {
Guard.shouldNotBeNull(key, "key");
OperationFuture<Boolean> setOp = nativeCache.set(getKey(key), expireMillis, value);
if (setOp.getStatus().isSuccess()) {
if (log.isDebugEnabled())
log.debug("객체를 캐시 키[{}]로 저장했습니다.", key);
} else {
if (log.isDebugEnabled())
log.debug("객체를 캐시 키[{}]로 저장하는데 실패했습니다. operation=[{}]", key, setOp);
}
}
@Override
public void evict(Object key) {
Guard.shouldNotBeNull(key, "key");
if (log.isDebugEnabled())
log.debug("delete cache item... key=[{}]", key);
nativeCache.delete(key.toString());
}
@Override
public void clear() {
if (log.isDebugEnabled())
log.debug("clear cache...");
nativeCache.flush();
}
}


3. CouchbaseCacheConfiguration

@Configuration
@EnableCaching
@ComponentScan(basePackageClasses = {UserRepository.class})
@Slf4j
public class CouchbaseCacheConfiguration {
@Bean
public List<URI> couchbaseList() {
List<URI> uris = Lists.newArrayList(URI.create("http://localhost:8091/pools"));
return uris;
}
@Bean
public CouchbaseClient couchbaseClient() throws IOException {
return new CouchbaseClient(couchbaseList(), "default", "");
}
@Bean
public CouchbaseCacheManager couchbaseCacheManager() throws IOException {
return new CouchbaseCacheManager(couchbaseClient());
}
}

환경 설정은 각자 환경에 맞추면 됩니다만, default bucket 만 비밀번호 없이 접근이 가능합니다.
다른 bucket 을 사용하려면, 미리 만드시고, 보안을 설정하셔야 합니다.

4. Couchbase Admin Screenshot



이제 남은 건 Redis 만 남았네요... 요건 다음 기회에...

댓글 없음: