分佈式ehcache緩存

今天在這裏了記錄一下學習ehcache分佈式集羣的過程。
ehcache的三種最爲經常使用集羣方式,分別是 RMI、JGroups 以及 EhCache Server 。
這裏主要講一下rmi方式。java

一、添加依賴

<dependency>
  <groupId>net.sf.ehcache</groupId>
  <artifactId>ehcache</artifactId>
  <version>2.10.3</version>
</dependency>

二、配置文件

spring.xml:spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

    <!-- 自動掃描註解的bean -->
    <context:component-scan base-package="com.yitop.feng" />

    <!-- 啓用緩存註解功能(請將其配置在Spring主配置文件中) -->
    <cache:annotation-driven cache-manager="cacheManager" />

    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="ehcache"></property>
    </bean>

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

</beans>

server1的ehcache.xml:bootstrap

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd">

    <!--
    配置提供者
        一、peerDiscovery,提供者方式,有兩種方式:自動發現(automatic)、手動配置(manual)
        二、rmiUrls,手動方式時提供者的地址,多個的話用|隔開
    -->
    <cacheManagerPeerProviderFactory
            class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
            properties="peerDiscovery=manual,rmiUrls=//192.168.30.51:40002/cachetest"
    />

    <!--
    配置監聽器
        一、hostName 主機地址
        二、port 端口
        三、socketTimeoutMillis socket子模塊的超時時間,默認是2000ms
    -->
    <cacheManagerPeerListenerFactory
            class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
            properties="hostName=192.168.30.51, port=40001, socketTimeoutMillis=2000"
    />

    <!-- 默認緩存 -->
    <defaultCache
            maxEntriesLocalHeap="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"/>


    <!-- cachetest緩存 緩存時間爲5秒 -->
    <cache name="cachetest"
           maxElementsInMemory="1000"
           eternal="false"
           timeToIdleSeconds="300"
           timeToLiveSeconds="300"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU">

        <!--
        配置緩存事件監聽器
            replicateAsynchronously  操做是否異步,默認值爲true.
            replicatePuts 添加操做是否同步到集羣內的其餘緩存,默認爲true.
            replicateUpdates 更新操做是否同步到集羣內的其餘緩存,默認爲true.
            replicateUpdatesViaCopy 更新以後的對象是否複製到集羣中的其餘緩存(true);
            replicateRemovals 刪除操做是否同步到集羣內的其餘緩存,默認爲true.
        -->
        <cacheEventListenerFactory
                class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
                properties="
                replicateAsynchronously=true,
                replicatePuts=true,
                replicateUpdates=true,
                replicateUpdatesViaCopy=true,
                replicateRemovals=true "/>

        <!-- 初始化緩存,以及自動設置-->
        <bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/>
    </cache>

</ehcache>

server2的ehcache.xml只要把提供者和監聽者的端口調換就能夠了緩存

三、測試

這裏是隨便寫個查詢和寫入緩存的方法服務器

@CachePut(value = "cachetest", key = "#key")
public String put(String key, String value) {
    System.out.println("保存數據, " + key + " : " + value);
    
    return value;
}

@Cacheable(value = "cachetest", key = "#name")
public String getName(String name) {
    return String.valueOf(System.currentTimeMillis());
}

下面是兩個測試類,模擬兩臺服務器
test1異步

package com.yitop.feng;

  import com.yitop.feng.service.EhcacheTestService;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.test.context.ContextConfiguration;
  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

  import java.util.Scanner;

  /**
   * @author fengzp
   * @date 17/3/1下午2:19
   * @email fengzp@gzyitop.com
   * @company 廣州易站通計算機科技有限公司
   */
  @RunWith(SpringJUnit4ClassRunner.class)
  @ContextConfiguration(locations = {"classpath:spring.xml"})
  public class EhcacheTest {

      @Autowired
      private EhcacheTestService ehcacheTestService;

      @Test
      public void test() throws InterruptedException {
          String name = "feng";

          int i = 1;

          while (true){
              String o = ehcacheTestService.getName(name + i);
              System.out.println(i + " : " + o);
              i++;
              Thread.sleep(1000);
              if(i > 5) i = 1;
          }
      }
  }

test2:socket

package com.yitop.feng;

  import com.yitop.feng.service.EhcacheTestService;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.cache.Cache;
  import org.springframework.test.context.ContextConfiguration;
  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

  import java.util.Scanner;

  /**
   * @author fengzp
   * @date 17/3/1下午2:19
   * @email fengzp@gzyitop.com
   * @company 廣州易站通計算機科技有限公司
   */
  @RunWith(SpringJUnit4ClassRunner.class)
  @ContextConfiguration(locations = {"classpath:test2/spring2.xml"})
  public class EhcacheTest2 {

      @Autowired
      private EhcacheTestService ehcacheTestService;

      @Test
      public void test() throws InterruptedException {

          String name = "feng";

          int i = 1;

          while (true){
              String o = ehcacheTestService.getName(name + i);
              System.out.println(i + " : " + o);
              i++;
              if(i > 5){
                  i = 1;
                  break;
              }
          }

          Thread.sleep(5000);

          while (true) {
              ehcacheTestService.put(name + i, i++ + "");
              if(i > 5) break;
          }

          while (true){

          }

      }
  }

四、結果

這裏先啓動test1,等它把數據都寫到緩存後,啓動test2。能夠看到test2啓動後可以讀取到test1的緩存, 而且以後test2更新緩存後,test1也能同時更新,說明緩存已經成功集羣到兩邊。分佈式

相關文章
相關標籤/搜索