您的位置:首页 > 数据库 > Memcache

Java使用Memcached

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

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

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

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

1、缓存工具类

2、hibernate的provider

3、用缓存实现session机制

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

首先是工具类的实现:

在Spring中配置

Java代码

<!-- EhCache Manager -->

<bean id="cacheManager"

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

<property name="configLocation">

<value>classpath:ehcache.xml</value>

</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();

}

}

}

然后实现函数的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;

}

}

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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: