用户登录
用户注册

分享至

spring整合memcached

  • 作者: 爱上你是我的错134
  • 来源: 51数据库
  • 2020-10-18

本文将对在Java环境下Memcached应用进行详细介绍。Memcached主要是集群环境下的缓存解决方案,可以运行在Java或者.NET平台上,这里我们主要讲的是Windows下的Memcached应用。


  这些天在设计SNA的架构,接触了一些远程缓存、集群、session复制等的东西,以前做企业应用的时候感觉作用不大,现在设计面对internet的系统架构时就非常有用了,而且在调试后看到压力测试的情况还是比较好的。


  在缓存的选择上有过很多的思考,虽然说memcached结合java在序列化上性能不怎么样,不过也没有更好的集群环境下的缓存解决方案了,就选择了memcached。本来计划等公司买的服务器到位装个linux再来研究memcached,但这两天在找到了一个windows下的Memcached版本,就动手开始调整现有的框架了。


  Windows下的Server端很简单,不用安装,双击运行后默认服务端口是11211,没有试着去更改端口,因为反正以后会用Unix版本,到时再记录安装步骤。下载客户端的JavaAPI包,接口非常简单,参考API手册上就有现成的例子。


  目标,对旧框架缓存部分进行改造:


  1、缓存工具类


  2、hibernate的provider


  3、用缓存实现session机制


  今天先研究研究缓存工具类的改造,在旧框架中部分函数用了ehcache对执行结果进行了缓存处理,现在目标是提供一个缓存工具类,在配置文件中配置使用哪种缓存(memcached或ehcached),使其它程序对具体的缓存不依赖,同时使用AOP方式来对方法执行结果进行缓存。


  首先是工具类的实现:


  在Spring中配置

  Java代码


  <bean id="cacheManager"

  class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">

  <property name="configLocation">

  <value>classpath:ehcache.xmlvalue>

  property>

  bean>


  <bean id="localCache"

  class="org.springframework.cache.ehcache.EhCacheFactoryBean">

  <property name="cacheManager" ref="cacheManager" />

  <property name="cacheName"

  value="×××.cache.LOCAL_CACHE" />

  bean>


  <bean id="cacheService"

  class="×××.core.cache.CacheService" init-method="init" destroy-method="destory">

  <property name="cacheServerList" value="${cache.servers}"/>

  <property name="cacheServerWeights" value="${cache.cacheServerWeights}"/>

  <property name="cacheCluster" value="${cache.cluster}"/>

  <property name="localCache" ref="localCache"/>

  bean>


  <bean id="cacheManager"

  class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">

  <property name="configLocation">

  <value>classpath:ehcache.xmlvalue>

  property>

  bean>

  <bean id="localCache"

  class="org.springframework.cache.ehcache.EhCacheFactoryBean">

  <property name="cacheManager" ref="cacheManager" />

  <property name="cacheName"

  value="×××.cache.LOCAL_CACHE" />

  bean>


  <bean id="cacheService"

  class="×××.core.cache.CacheService" init-method="init" destroy-method="destory">

  <property name="cacheServerList" value="${cache.servers}"/>

  <property name="cacheServerWeights" value="${cache.cacheServerWeights}"/>

  <property name="cacheCluster" value="${cache.cluster}"/>

  <property name="localCache" ref="localCache"/>

  bean>

  在properties文件中配置${cache.servers} ${cache.cacheServerWeights} ${cache.cluster}


  具体工具类的代码


  Java代码

  /**

  * @author Marc

  *

  */

  public class CacheService {

  private Log logger = LogFactory.getLog(getClass());

  private Cache localCache;

  String cacheServerList;

  String cacheServerWeights;

  boolean cacheCluster = false;

  int initialConnections = 10;

  int minSpareConnections = 5;

  int maxSpareConnections = 50;

  long maxIdleTime = 1000 * 60 * 30; // 30 minutes

  long maxBusyTime = 1000 * 60 * 5; // 5 minutes

  long maintThreadSleep = 1000 * 5; // 5 seconds

  int socketTimeOut = 1000 * 3; // 3 seconds to block on reads

  int socketConnectTO = 1000 * 3; // 3 seconds to block on initial

  // connections. If 0, then will use blocking

  // connect (default)

  boolean failover = false; // turn off auto-failover in event of server

  // down

  boolean nagleAlg = false; // turn off Nagle's algorithm on all sockets in

  // pool

  MemCachedClient mc;

  public CacheService(){

  mc = new MemCachedClient();

  mc.setCompressEnable(false);

  }

  /**

  * 放入

  *

  */

  public void put(String key, Object obj) {

  Assert.hasText(key);

  Assert.notNull(obj);

  Assert.notNull(localCache);

  if (this.cacheCluster) {

  mc.set(key, obj);

  } else {

  Element element = new Element(key, (Serializable) obj);

  localCache.put(element);

  }

  }

  /**

  * 删除

  */

  public void remove(String key){

  Assert.hasText(key);

  Assert.notNull(localCache);

  if (this.cacheCluster) {

  mc.delete(key);

  }else{

  localCache.remove(key);

  }

  }

  /**

  * 得到

  */

  public Object get(String key) {

  Assert.hasText(key);

  Assert.notNull(localCache);

  Object rt = null;

  if (this.cacheCluster) {

  rt = mc.get(key);

  } else {

  Element element = null;

  try {

  element = localCache.get(key);

  } catch (CacheException cacheException) {

  throw new DataRetrievalFailureException("Cache failure: "

  + cacheException.getMessage());

  }

  if(element != null)

  rt = element.getValue();

  }

  return rt;

  }

  /**

  * 判断是否存在

  *

  */

  public boolean exist(String key){

  Assert.hasText(key);

  Assert.notNull(localCache);

  if (this.cacheCluster) {

  return mc.keyExists(key);

  }else{

  return this.localCache.isKeyInCache(key);

  }

  }

  private void init() {

  if (this.cacheCluster) {

  String[] serverlist = cacheServerList.split(",");

  Integer[] weights = this.split(cacheServerWeights);

  // initialize the pool for memcache servers

  SockIOPool pool = SockIOPool.getInstance();

  pool.setServers(serverlist);

  pool.setWeights(weights);

  pool.setInitConn(initialConnections);

  pool.setMinConn(minSpareConnections);

  pool.setMaxConn(maxSpareConnections);

  pool.setMaxIdle(maxIdleTime);

  pool.setMaxBusyTime(maxBusyTime);

  pool.setMaintSleep(maintThreadSleep);

  pool.setSocketTO(socketTimeOut);

  pool.setSocketConnectTO(socketConnectTO);

  pool.setNagle(nagleAlg);

  pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);

  pool.initialize();

  logger.info("初始化memcached pool!");

  }

  }


  private void destory() {

  if (this.cacheCluster) {

  SockIOPool.getInstance().shutDown();

  }

  }

  }

  /**

  * @author Marc

  *

  */

  public class CacheService {

  private Log logger = LogFactory.getLog(getClass());

  private Cache localCache;

  String cacheServerList;

  String cacheServerWeights;

  boolean cacheCluster = false;

  int initialConnections = 10;

  int minSpareConnections = 5;

  int maxSpareConnections = 50;

  long maxIdleTime = 1000 * 60 * 30; // 30 minutes

  long maxBusyTime = 1000 * 60 * 5; // 5 minutes

  long maintThreadSleep = 1000 * 5; // 5 seconds

  int socketTimeOut = 1000 * 3; // 3 seconds to block on reads

  int socketConnectTO = 1000 * 3; // 3 seconds to block on initial

  // connections. If 0, then will use blocking

  // connect (default)

  boolean failover = false; // turn off auto-failover in event of server

  // down

  boolean nagleAlg = false; // turn off Nagle's algorithm on all sockets in

  // pool

  MemCachedClient mc;

  public CacheService(){

  mc = new MemCachedClient();

  mc.setCompressEnable(false);

  }

  /**

  * 放入

  *

  */

  public void put(String key, Object obj) {

  Assert.hasText(key);

  Assert.notNull(obj);

  Assert.notNull(localCache);

  if (this.cacheCluster) {

  mc.set(key, obj);

  } else {

  Element element = new Element(key, (Serializable) obj);

  localCache.put(element);

  }

  }

  /**

  * 删除

  */

  public void remove(String key){

  Assert.hasText(key);

  Assert.notNull(localCache);

  if (this.cacheCluster) {

  mc.delete(key);

  }else{

  localCache.remove(key);

  }

  }

  /**

  * 得到

  */

  public Object get(String key) {

  Assert.hasText(key);

  Assert.notNull(localCache);

  Object rt = null;

  if (this.cacheCluster) {

  rt = mc.get(key);

  } else {

  Element element = null;

  try {

  element = localCache.get(key);

  } catch (CacheException cacheException) {

  throw new DataRetrievalFailureException("Cache failure: "

  + cacheException.getMessage());

  }

  if(element != null)

  rt = element.getValue();

  }

  return rt;

  }

  /**

  * 判断是否存在

  *

  */

  public boolean exist(String key){

  Assert.hasText(key);

  Assert.notNull(localCache);

  if (this.cacheCluster) {

  return mc.keyExists(key);

  }else{

  return this.localCache.isKeyInCache(key);

  }

  }

  private void init() {

  if (this.cacheCluster) {

  String[] serverlist = cacheServerList.split(",");

  Integer[] weights = this.split(cacheServerWeights);

  // initialize the pool for memcache servers

  SockIOPool pool = SockIOPool.getInstance();

  pool.setServers(serverlist);

  pool.setWeights(weights);

  pool.setInitConn(initialConnections);

  pool.setMinConn(minSpareConnections);

  pool.setMaxConn(maxSpareConnections);

  pool.setMaxIdle(maxIdleTime);

  pool.setMaxBusyTime(maxBusyTime);

  pool.setMaintSleep(maintThreadSleep);

  pool.setSocketTO(socketTimeOut);

  pool.setSocketConnectTO(socketConnectTO);

  pool.setNagle(nagleAlg);

  pool.setHashingAlg(SockIOPool.NEW_COMPAT_HASH);

  pool.initialize();

  logger.info("初始化memcachedpool!");

  }

  }

  private void destory() {

  if (this.cacheCluster) {

  SockIOPool.getInstance().shutDown();

  }

  }

  }

  然后实现函数的AOP拦截类,用来在函数执行前返回缓存内容


  Java代码

  public class CachingInterceptor implements MethodInterceptor {


  private CacheService cacheService;

  private String cacheKey;


  public void setCacheKey(String cacheKey) {

  this.cacheKey = cacheKey;

  }


  public void setCacheService(CacheService cacheService) {

  this.cacheService = cacheService;

  }


  public Object invoke(MethodInvocation invocation) throws Throwable {

  Object result = cacheService.get(cacheKey);

  //如果函数返回结果不在Cache中,执行函数并将结果放入Cache

  if (result == null) {

  result = invocation.proceed();

  cacheService.put(cacheKey,result);

  }

  return result;

  }

  }

  public class CachingInterceptor implements MethodInterceptor {


  private CacheService cacheService;

  private String cacheKey;


  public void setCacheKey(String cacheKey) {

  this.cacheKey = cacheKey;

  }


  public void setCacheService(CacheService cacheService) {

  this.cacheService = cacheService;

  }


  public Object invoke(MethodInvocation invocation) throws Throwable {

  Object result = cacheService.get(cacheKey);

  //如果函数返回结果不在Cache中,执行函数并将结果放入Cache

  if (result == null) {

  result = invocation.proceed();

  cacheService.put(cacheKey,result);

  }

  return result;

  }

  }

  Spring的AOP配置如下:


  Java代码


  <aop:config proxy-target-class="true">

  <aop:advisor

  pointcut="execution(* ×××.PoiService.getOne(..))"

  advice-ref="PoiServiceCachingAdvice" />

  aop:config>


  <bean id="BasPoiServiceCachingAdvice"

  class="×××.core.cache.CachingInterceptor">

  <property name="cacheKey" value="PoiService" />

  <property name="cacheService" ref="cacheService" />

  bean>


软件
前端设计
程序设计
Java相关