Cache 서비스

개요

전자정부 프레임워크에서 Cache Service는 EhCache를 선정하여 가이드한다. 변경이 자주 일어나지 않지만 사용빈도가 높고 생성하는데 비용이 많이 드는 객체일 경우, Cache를 이용하면 다음과 같은 장점을 얻을 수 있다.

  • 자주 접근하는 데이터를 매번 데이터베이스로부터 fetch할 필요가 없으므로 오버헤드가 줄어든다.
  • 객체를 매번 생성하지 않기 때문에 메모리를 효율적으로 사용할 수 있다.

설명

Cache를 이용하기 위한 기본 설정 및 기본 사용법에 대해서 설명한다.

Bootstrap Source

Cache를 사용하기 위해서 Cache Manager를 생성하는 방법을 샘플을 통해서 설명한다.

//클래스 패스를 이용하여 설정파일 읽어서 Cache Manager 생성하기.
URL url = getClass().getResource("/ehcache-default.xml");
manager = new CacheManager(url);

위에서 getResource를 통해서 읽어들이는 /ehcache-default.xml 의 파일 내용은 다음과 같다.

Configuration

<ehcache>
<diskStore path="user.dir/second"/>
   <cache name="sampleMem"
           maxElementsInMemory="3"
           eternal="false"
           timeToIdleSeconds="360"
           timeToLiveSeconds="1000"
           overflowToDisk="false"
           diskPersistent="false"  
           memoryStoreEvictionPolicy="LRU">
   </cache>
</ehcache>

Basic Usage Source

위에서 정의한 Cache Manager에서 Cache를 얻어서 기본적인 쓰고 읽고 지우는 것에 대한 샘플은 다음과 같다.

// cache Name을 가지고 cache 얻기
Cache cache = manager.getCache("sampleMem");
 
// 1.Cache에 데이터 입력
cache.put(new Element("key1", "value1"));
 
// 2.Cache로부터 입력한 데이터 읽기
Element value = cache.get("key1");
 
// 3. Cache에서 데이터 삭제
cache.remove("key1");
  • manager.getCache : Manager를 이용하여 해당하는 Cache 얻기
  • cache.put : Cache에 자료 입력 ( 같은 키 값에 대해서 다른 value를 입력하면 수정처리됨 )
  • cache.get : Cache에서 자료 읽기
  • cache.remove: Cache에서 자료 삭제.

Cache Algorithm

Cache는 메모리를 이용하는 것을 기본으로 하기에 꼭 필요한 자료만을 관리하도록 보관 사이즈를 지정하고 보관 사이즈를 넘어설 경우 불필요한 자료부터 삭제처리하는데 필요한 자료에 대한 판단은 알고리즘을 통해서 한다. 지원되는 알고리즘은 LRU,FIFO,LFU 세가지 이고 각각에 대한 설정및 사용법은 아래와 같다.

LRU Algorithm

최근에 이용한 것을 남기는 알고리즘으로 설정은 아래와 같이 한다.

Cofiguration

   <cache name="sampleMem"
           maxElementsInMemory="3"
           ...
           memoryStoreEvictionPolicy="LRU">

위의 설정에서 최대 보관 엔트리 갯수(maxElementsInMemory)는 3으로 알고리즘은 LRU 로 설정된 것을 확인할 수 있다. 이 설정을 이용하여 설정에 대한 결과를 확인하는 소스는 다음과 같다.

Sample Source

   Cache cache = manager.getCache("sampleMem");
   ...
   cache.get("key2");
   cache.get("key2");
   cache.get("key1");
   cache.get("key1");
   cache.get("key3");
 
   // 4. Put New element in cache.
   cache.put(new Element("key4", "value4"));    	
 
   // 5. get key2 but can't key2 
   assertNull("Can't get key2",cache.get("key2"));

FIFO Algorithm

먼저 입력된것을 제거하는 알고리즘으로 설정은 아래와 같이 한다.

Cofiguration

   <cache name="sampleMemFIFO"
           maxElementsInMemory="3"
           ...
           memoryStoreEvictionPolicy="FIFO">

위의 설정에서 최대 보관 엔트리 갯수(maxElementsInMemory)는 3으로 알고리즘은 FIFO 로 설정된 것을 확인할 수 있다. 이 설정을 이용하여 설정에 대한 결과를 확인하는 소스는 다음과 같다.

Sample Source

   Cache cache = manager.getCache("sampleMemFIFO");
   cache.put(new Element("key1", "value1")); 
   cache.put(new Element("key2", "value2")); 
   cache.put(new Element("key3", "value3")); 
   ...
   cache.get("key2");
   cache.get("key2");
   cache.get("key1");
   cache.get("key1");
   cache.get("key3");
 
   // 4. Put New element in cache.
   cache.put(new Element("key4", "value4"));    	
 
   // 5. get key1 but can't key1 
   assertNull("Can't get key1",cache.get("key1"));

LFU Algorithm

가장 적게 이용된 것을 제거하는 알고리즘으로 설정은 아래와 같이 한다.

Cofiguration

   <cache name="sampleMemLFU"
           maxElementsInMemory="3"
           ...
           memoryStoreEvictionPolicy="LFU">

위의 설정에서 최대 보관 엔트리 갯수(maxElementsInMemory)는 3으로 알고리즘은 LFU 로 설정된 것을 확인할 수 있다. 이 설정을 이용하여 설정에 대한 결과를 확인하는 소스는 다음과 같다.

Sample Source

   Cache cache = manager.getCache("sampleMemLFU");
   cache.put(new Element("key1", "value1")); 
   cache.put(new Element("key2", "value2")); 
   cache.put(new Element("key3", "value3")); 
   ...
   cache.get("key2");
   cache.get("key2");
   cache.get("key1");
   cache.get("key1");
   cache.get("key3");
 
   // 4. Put New element in cache.
   cache.put(new Element("key4", "value4"));    	
 
   // 5. get key2 but can't key3 
   assertNull("Can't get key3",cache.get("key3"));

Cache Size & Device

Cache에서 관리해야 하는 정보의 사이즈 설정 및 저장 디바이스 관련 설정을 할 수 있다.

Cache Device

디바이스 관련 세팅은 메모리 관리 캐쉬의 디스크 관리로의 이동관련 설정으로 메모리 관리 오브젝트 수가 넘었을때 Disk 로 이동여부, flush 호출시 파일로 저장 여부에대한 세팅이 있다. 이에 대한 세팅은 다음과 같다.

Configuration

<cache name="sampleDisk"
       overflowToDisk="true"
       diskPersistent="true"  
       ...>
</cache>
  • overflowToDisk : 메모리 관리 오브젝트 넘었을때 Disk로 이동 여부 ( true,false )
  • diskPersistent : flush시에 파일로 저장 여부 ( trun , false )

이 설정을 이용하여 설정에 대한 결과를 확인하는 소스는 다음과 같다

Sample Source

   Ehcache cache = manager.getCache("sampleDisk");
 
   // 1. Put a content in Cache.
   cache.put(new Element("key1", "value1"));
 
   // 2. Get that item from Cache.
   Element value = cache.get("key1");
   assertEquals("value1", value.getValue().toString());
 
   // 3. flush 를 한다.
   cache.flush();		
   File dataFile = new File(manager.getDiskStorePath()+ File.separator + "sampleDisk.data");
   // 4. 파일로 저장 확인
   assertTrue("File exists", dataFile.exists());

위의 샘플에서 flush 수행시 파일로 저장되는 것을 확인 할 수 있고, 메모리 관리 오브젝트 Disk이동 여부는 아래의 Cache Size의 예에서 확인한다.

Cache Size

사이즈 관련 세팅은 메모리에서 관리해야 할 최대 오브젝트 수, 디스크에서 관리하는 최대 오브젝트 수에 대한 세팅이 있다. 이에 대한 세팅은 다음과 같다.

Configuration

<cache name="sampleDisk"
       maxElementsInMemory="3"
       maxElementsOnDisk="2"
       overflowToDisk="true"
       ...>
</cache>
  • maxElementsInMemory : 메모리에서 관리하는 최대 오브젝트 수
  • maxElementsOnDisk : 디스크에서 관리하는 최대 오브젝트 수

이 설정을 이용하여 설정에 대한 결과를 확인하는 소스는 다음과 같다

Sample Source

   Cache cache = manager.getCache("sampleDisk");
 
   // 1. Put 3 contents in Cache.
   cache.put(new Element("key1", "value1"));
   cache.put(new Element("key2", "value2"));
   cache.put(new Element("key3", "value3"));
 
   // 2. Put Fourth content in Cache.
   cache.put(new Element("key4", "value4"));
   assertEquals(3, cache.getMemoryStoreSize()); //Memory에는 세개 유지함
   assertEquals(1, cache.getDiskStoreSize());   //Disk로 하나 넘어감.
 
   // 3. Put 5~7 contens in Cache.    
   cache.put(new Element("key5", "value5"));
   cache.put(new Element("key6", "value6"));
   cache.put(new Element("key7", "value7"));
 
   // Disk Max Size에 관계 없이 모두 넘어감
   assertEquals(3, cache.getMemoryStoreSize()); //Memory에는 세개 유지함
   assertEquals(4, cache.getDiskStoreSize());   //Disk에는 2개를 넘어서서 4개 유지함.
 
   // 메모리것을 디스크로 이동시킴
    cache.flush();
   // Disk의 Max Size 대로 변경됨.
   assertEquals(0, cache.getMemoryStoreSize()); //Memory에는 없어짐.
   assertEquals(2, cache.getDiskStoreSize());   //Disk에는 DiskMaxSize 대로 2개만 남김.

위의 예를 보면 cache.put에 의해서는 Disk의 MaxSize에 관계없이 계속 Memory에서 Disk로 넘어가지만 flush를 수행하면 최대 디스크 보관수만을 남기는 것을 확인 할 수 있다.

Distributed Cache

Ehcache는 Distributed Cache를 지원하는 방법으로 RMI,JGROUP,JMS등을 지원한다. 그 중에서 JGROUP와 ActiveMQ를 이용한 JMS 지원 설정 및 사용 방법을 설명한다. 자세한 설명은 EhcacheUserGuide 참고.

Using JGroups

JGroups는 multicast 기반의 커뮤니케이션 툴킷으로 그룹을 생성하고 그룹멤버간에 메세지를 주고 받을 수 있도록 지원한다. 관련한 자세한 정보는 사이트참조

Configuration

    <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
                                     properties="connect=UDP(mcast_addr=224.10.10.10;mcast_port=5555;ip_ttl=32;
                                     mcast_send_buf_size=150000;mcast_recv_buf_size=80000):
                                     PING(timeout=2000;num_initial_members=6):
                                     MERGE2(min_interval=5000;max_interval=10000):
                                     FD_SOCK:VERIFY_SUSPECT(timeout=1500):
                                     pbcast.NAKACK(gc_lag=10;retransmit_timeout=3000):
                                     UNICAST(timeout=5000):
                                     pbcast.STABLE(desired_avg_gossip=20000):
                                     FRAG:
                                     pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=false)"
                                     propertySeparator="::"/>
    <cache name="cacheSync"
           maxElementsInMemory="1000"
           eternal="false"
           timeToIdleSeconds="1000"
           timeToLiveSeconds="1000"
           overflowToDisk="false">
        <cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
                                   properties="replicateAsynchronously=false, replicatePuts=true,
 												replicateUpdates=true, replicateUpdatesViaCopy=false,
 												replicateRemovals=true"/>
    </cache>

이 설정을 이용하여 설정에 대한 결과를 확인하는 소스는 다음과 같다

Sample Source

   // 위의 설정파일을 정보 읽어오기
   URL url = this.getClass().getResource("/ehcache-distributed-jgroups.xml");
   // 두개의 Cache Manager 생성
   manager1 = new CacheManager(url);
   manager2 = new CacheManager(url);
 
   for (int i = 0; i < 10 ; i++) {
      manager1.getEhcache(CACHE_SYNC).put(new Element(new Integer(i), "value"));
   }		
   // 리플리케이션을 위한 시간 필요함.     
   Thread.currentThread().sleep(100);
   // 리플리케이션이 되어 manager2에도 동일한 Cache 정보 입력됨 확인.
   assertTrue(manager1.getEhcache(CACHE_SYNC).getKeys().size() == manager2.getEhcache(CACHE_SYNC).getKeys().size() );

Using ActiveMQ

ActiveMQ는 JMS 메세징 서비스를 제공하는 오픈 소스이다. 관련한 자세한 정보는 사이트참조

Configuration

    <cacheManagerPeerProviderFactory
            class="net.sf.ehcache.distribution.jms.JMSCacheManagerPeerProviderFactory"
            properties="initialContextFactoryName=egovframework.rte.fdl.cache.distribute.TestActiveMQInitialContextFactory,
                providerURL=tcp://localhost:61616,
                replicationTopicConnectionFactoryBindingName=topicConnectionFactory,
                getQueueConnectionFactoryBindingName=queueConnectionFactory,
                replicationTopicBindingName=ehcache,
                getQueueBindingName=ehcacheGetQueue"
            propertySeparator=","
            />
 
    <cache name="CacheAsync"
           maxElementsInMemory="1000"
           eternal="false"
           timeToIdleSeconds="1000"
           timeToLiveSeconds="1000"
           overflowToDisk="false">
 
           <cacheEventListenerFactory class="net.sf.ehcache.distribution.jms.JMSCacheReplicatorFactory"
                                   properties="replicateAsynchronously=true, 
                                                replicatePuts=true,
                                                replicateUpdates=true,
                                                replicateUpdatesViaCopy=true,
                                                replicateRemovals=true,
                                                asynchronousReplicationIntervalMillis=1000"
                                    propertySeparator=","/>
    </cache>

이 설정을 이용하여 설정에 대한 결과를 확인하는 소스는 다음과 같다

Sample Source

   URL url = this.getClass().getResource("/ehcache-distributed-activemq.xml");
   manager1 = new CacheManager(url);
   manager2 = new CacheManager(url);
 
   cacheName = "CacheAsync";
   for (int i = 0; i < 10 ; i++) {
      manager1.getEhcache("CacheAsync").put(new Element(new Integer(i), "value"));
   }		
 
   // replication 되는데 일정 시간이 필요함.
   Thread.currentThread().sleep(1000);
 
   assertTrue(manager1.getEhcache("CacheAsync").getKeys().size() == manager2.getEhcache("CacheAsync").getKeys().size() );

6. Spring Integration

Spring에서 Ehcache를 이용하는 방법에 대해서 설정 및 설정을 이용한 기본 Cache 서비스에 대해서 설명한다.

Configuration - Spring Application Context

   <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
      <property name="cacheManager">
         <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
            <property name="configLocation" value="classpath:ehcache-default.xml"/>
         </bean>
      </property>    
   </bean>

위와 같이 설정하면 Manager를 통하지 않고서 cache를 얻을 수 있다. ConfigLocation에 정의된 ehcache-default.xml은 Cache Basic의 Configuration에 설명한 설정파일과 동일한 것이다.

Sample Source

   @Resource(name="ehcache")
   Ehcache gCache ;
 
   // cache Name을 가지고 cache 찾기
    Ehcache cache = gCache.getCacheManager().getCache("sampleMem");    	
 
   cache.put(new Element("key1", "value1"));
   Element value = cache.get("key1");

위의 예를 보면 ehcache를 이용하여 Ehcache를 가지고 오고 getCacheManager()를 통해서 이름을 통한 cache 정보를 읽어오는 것을 확인할 수 있다. 그 이후에는 위에서 설명한 것과 동일한 방식으로 사용하는 것을 확인 할 수 있다.

참고자료

 
egovframework/rte/fdl/cache.txt · 마지막 수정: 2015/04/14 11:24 (외부 편집기)
 
이 위키의 내용은 다음의 라이센스에 따릅니다 :CC Attribution-Noncommercial-Share Alike 3.0 Unported
전자정부 표준프레임워크 라이센스(바로가기)

전자정부 표준프레임워크 활용의 안정성 보장을 위해 위험성을 지속적으로 모니터링하고 있으나, 오픈소스의 특성상 문제가 발생할 수 있습니다.
전자정부 표준프레임워크는 Apache 2.0 라이선스를 따르고 있는 오픈소스 프로그램입니다. Apache 2.0 라이선스에 따라 표준프레임워크를 활용하여 발생된 업무중단, 컴퓨터 고장 또는 오동작으로 인한 손해 등에 대해서 책임이 없습니다.
Recent changes RSS feed CC Attribution-Noncommercial-Share Alike 3.0 Unported Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki