Programing/Java

Guava Cache

BUST 2018. 9. 12. 22:14

Guava Cache

데이터를 계속 읽을 필요가 없을 경우 캐쉬를 이용하여 처리를 할수 있다. 일반적으로 엔티티를 캐쉬도 하지만 설정(Config) 같이 자주 바뀌지 않는 값을 Cache를 이용하여 활용할수 있다.
Guava Cache는 Local에서 작동되는 캐쉬이기 때문에 클러스터에서는 공유가 되지 않는다. 이경우에는 Memcached, Redis 를 활용한다.

Example

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()

       .maximumSize(1000)

       .expireAfterWrite(10, TimeUnit.MINUTES)

       .removalListener(MY_LISTENER)

       .build(

           new CacheLoader<Key, Graph>() {

             public Graph load(Key key) throws AnyException {

               return createExpensiveGraph(key);

             }

           });

  • CacheLoader 인터페이스를 이용하여 해당하는 key값에 대한 읽기 로직을 구현을 하면 된다.


Size-based Eviction

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .maximumWeight(100000)
       .weigher(new Weigher<Key, Graph>() {
          public int weigh(Key k, Graph g) {
            return g.vertices().size();
          }
        })
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) { // no checked exception
               return createExpensiveGraph(key);
             }
           });
  • 객체의 크기 (size)을 기반으로 캐쉬 정책을 가지고 갈수가 있다
  • 객체의 크기가 크다는 의미는 그만큼 무겁게 읽어올수 있기 때문에 크기가 큰 객체를 캐쉬 할때 활용된다.

Timed Eviction

  • 시간을 기반으로 캐쉬 정책을 설정을 할수가 있다.
    • expireAfterAccess(long, TimeUnit) 
      • access (read) 이후 특정 시간이 지나면 만료(expire) 한다
    • expireAfterWrite(long, TimeUnit)
      • write 이후 특정 시간이 지나면 만료(expire) 한다.

Refresh

// Some keys don't need refreshing, and we want refreshes to be done asynchronously.
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .maximumSize(1000)
       .refreshAfterWrite(1, TimeUnit.MINUTES)
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) { // no checked exception
               return getGraphFromDatabase(key);
             }

             public ListenableFuture<Graph> reload(final Key key, Graph prevGraph) {
               if (neverNeedsRefresh(key)) {
                 return Futures.immediateFuture(prevGraph);
               } else {
                 // asynchronous!
                 ListenableFutureTask<Graph> task = ListenableFutureTask.create(new Callable<Graph>() {
                   public Graph call() {
                     return getGraphFromDatabase(key);
                   }
                 });
                 executor.execute(task);
                 return task;
               }
             }
           });
  • `refreshAfterWrite` 메서드를 활용을 하면 특정 시간이후 자동으로 데이터를 다시 읽는다 (reload)
  • expireAfterAccess과 같은 eviction는 데이터를 로딩할때까지 기다리지만 refreshAfterWrite는 데이터가 로딩할때까지 예전 값 (old value)를 리턴을 한다
  • Read가 많고, Update가 적지만, 데이터의 로딩이 전체 스트림이 문제가 되는 경우 refresh 기능을 활용할수 있다.
  • 만약 re-load를 하다가 오류가 나는 경우에는 에러가 무시가 되고, 메세지만 출력되며 기존 값을 계속 유지해준다.


기타

Reference-based Eviction

  • GC가 Cache Eviciton 허용하는 설정, Week-Referecne를 가지고 있는다.

Explicit Removals

  • Cache Invalidate

Removal Listeners

  • 캐쉬된 값이 지워지는 경우 후작업을 처리할수 있도록 Listener를 등록할수있다
  • DB Connection 같이 관리가 필요한 경우 사용한다
  • 동기로 작동이 되기 때문에 Listener가 무거운 작업이면 전체 시스템을 영향을 미친다
    • 이경우에는 비동기 Listener를 사용한다.
      • RemovalListeners.asynchronous(RemovalListener, Executor)


'Programing > Java' 카테고리의 다른 글

Guava Eventbus @AllowConcurrentEvents  (0) 2018.10.10
CompletableFuture  (0) 2018.09.15
Singleton Pattern  (0) 2018.09.06
SLF4J(Simple Logging Facade for Java)  (0) 2018.09.01
Executor service  (0) 2018.08.31