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> 

<!-- 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();  
        }  
    }  


/**
* @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;  
    }  


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> 


实现hibernate的cache provider,让hibernate使用memcached缓存。
这里比较简单,由于memcached的SockIOPool已经在(一)中spring中初始化了,这里就不考虑pool的初始化,直接获得MemCachedClient使用即可。
然后配置给hibernate<prop key="hibernate.cache.provider_class">×××</prop>

附代码:
Java代码 
/** 
* @author Marc 

*/ 
public class MemcachedProvider implements CacheProvider {  
    public Cache buildCache(String name, Properties properties) throws CacheException {  
        return new MemCache(name);  
    }  
 
    public boolean isMinimalPutsEnabledByDefault() {  
        return false;  
    }  
 
    public long nextTimestamp() {  
        return Timestamper.next();  
    }  
 
    public void start(Properties properties) throws CacheException {  
    }  
 
    public void stop() {  
    }  
 


/**
* @author Marc
*
*/
public class MemcachedProvider implements CacheProvider {
public Cache buildCache(String name, Properties properties) throws CacheException {
return new MemCache(name);
}

public boolean isMinimalPutsEnabledByDefault() {
return false;
}

public long nextTimestamp() {
return Timestamper.next();
}

public void start(Properties properties) throws CacheException {
}

public void stop() {
}

}
Java代码 
/** 
* @author Marc 
*  
*/ 
public class MemCache implements Cache {  
    private static final Log log = LogFactory.getLog(MemCache.class);  
 
    private static final int SIXTY_THOUSAND_MS = 60000;  
 
    MemCachedClient mc;  
    String regionName;  
 
    /** 
     * Creates a new Hibernate pluggable cache based on a cache name. <p/> 
     *  
     * @param cache 
     *            The underlying EhCache instance to use. 
     */ 
    public MemCache(String regionName) {  
        mc = new MemCachedClient();  
        mc.setCompressEnable(false);  
        this.regionName = regionName;  
    }  
 
    /** 
     * Gets a value of an element which matches the given key. 
     *  
     * @param key 
     *            the key of the element to return. 
     * @return The value placed into the cache with an earlier put, or null if 
     *         not found or expired 
     * @throws CacheException 
     */ 
    public Object get(Object key) throws CacheException {  
        if (log.isDebugEnabled()) {  
            log.debug("key: " + key);  
        }  
        if (key == null) {  
            return null;  
        } else {  
            Object rt = mc.get(key.toString());  
            if (rt == null) {  
                if (log.isDebugEnabled()) {  
                    log.debug("Element for " + key + " is null");  
                }  
                return null;  
            } else {  
                return rt;  
            }  
        }  
 
    }  
 
    public Object read(Object key) throws CacheException {  
        return get(key);  
    }  
 
    /** 
     * Puts an object into the cache. 
     *  
     * @param key 
     *            a key 
     * @param value 
     *            a value 
     * @throws CacheException 
     *             if the {@link CacheManager} is shutdown or another 
     *             {@link Exception} occurs. 
     */ 
    public void update(Object key, Object value) throws CacheException {  
        put(key, value);  
    }  
 
    /** 
     * Puts an object into the cache. 
     *  
     * @param key 
     *            a key 
     * @param value 
     *            a value 
     * @throws CacheException 
     *             if the {@link CacheManager} is shutdown or another 
     *             {@link Exception} occurs. 
     */ 
    public void put(Object key, Object value) throws CacheException {  
        mc.set(key.toString(), value);  
    }  
 
    /** 
     * Removes the element which matches the key. <p/> If no element matches, 
     * nothing is removed and no Exception is thrown. 
     *  
     * @param key 
     *            the key of the element to remove 
     * @throws CacheException 
     */ 
    public void remove(Object key) throws CacheException {  
        mc.delete(key.toString());  
    }  
 
    /** 
     * Remove all elements in the cache, but leave the cache in a useable state. 
     *  
     * @throws CacheException 
     */ 
    public void clear() throws CacheException {  
        log.warn("cann't clear all items in memcached!");  
        throw new CacheException("cann't clear all items in memcached!");  
    }  
 
    /** 
     * Remove the cache and make it unuseable. 
     *  
     * @throws CacheException 
     */ 
    public void destroy() throws CacheException {  
 
    }  
 
    /** 
     * Calls to this method should perform there own synchronization. It is 
     * provided for distributed caches. Because EHCache is not distributed this 
     * method does nothing. 
     */ 
    public void lock(Object key) throws CacheException {  
    }  
 
    /** 
     * Calls to this method should perform there own synchronization. It is 
     * provided for distributed caches. Because EHCache is not distributed this 
     * method does nothing. 
     */ 
    public void unlock(Object key) throws CacheException {  
    }  
 
    /** 
     * Gets the next timestamp; 
     */ 
    public long nextTimestamp() {  
        return Timestamper.next();  
    }  
 
    /** 
     * Returns the lock timeout for this cache. 
     */ 
    public int getTimeout() {  
        // 60 second lock timeout  
        return Timestamper.ONE_MS * SIXTY_THOUSAND_MS;  
    }  
 
    public String getRegionName() {  
        return this.regionName;  
    }  
 
    /** 
     * Warning: This method can be very expensive to run. Allow approximately 1 
     * second per 1MB of entries. Running this method could create liveness 
     * problems because the object lock is held for a long period <p/> 
     *  
     * @return the approximate size of memory ehcache is using for the 
     *         MemoryStore for this cache 
     */ 
    public long getSizeInMemory() {  
        log.warn("cann't getSizeInMemory in memcached!");  
        throw new CacheException("cann't getSizeInMemory in memcached!");  
    }  
 
    public long getElementCountInMemory() {  
        log.warn("cann't getElementCountInMemory in memcached!");  
        throw new CacheException("cann't getElementCountInMemory in memcached!");  
    }  
 
    public long getElementCountOnDisk() {  
        log.warn("cann't getElementCountOnDisk in memcached!");  
        throw new CacheException("cann't getElementCountOnDisk in memcached!");  
    }  
 
    public Map toMap() {  
        log.warn("cann't toMap in memcached!");  
        throw new CacheException("cann't toMap in memcached!");  
    }  
 
    public String toString() {  
        return "MemCached(" + getRegionName() + ')';  
    }  
 
}

http://www.iteye.com/topic/28700

你可能感兴趣的:(memcached)