MemCached试用

来源:互联网 发布:linux开机自动启动服务 编辑:程序博客网 时间:2024/04/30 19:00
最近的一个业务需要频繁访问用户的个性信息,涉及到这些信息的页面没法做整体页面缓存,因为页面因用户而异,在数据库端做缓存也不现实,因为用户可能随时改变信息。初步想把用户信息塞到session中,但是因为我们的硬件条件没法做到负载均衡的session维持,最后决定采用每台前端应用服务器分割出一部分内存,一起做一个共享内存来存放用户信息,这样无论用户被分配到哪台服务器,对这个共享缓存的访问都是透明的。
MemCache是我们采用的解决方案。首先我们需要在每台应用服务器上安装MemCache,至于MemCache的安装很简单,google一下就可以了。MemCache的客户端有很多语言的实现,比如Java、C、PHP等等。这里有个概念需要说明,每一个MemCachedClient都需要一个SocketIOPool,这个pool管理MemCachedClient到服务器端的链接。为了方便使用,对MemCachedClient进行了一层封装
package com.aspire.pams.memcached;

import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.log4j.Logger;

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


public class MemCachedClientWrapper{
    
private final static Logger log = Logger.getLogger(MemCachedClientWrapper.class);
    
    
public final static long SECOND = 1000;
    
    
public final static long MINUTE = 1000 * 60;
    
    
public final static long HOUR = 1000 * 60 * 60;
    
    
private SockIOPool pool;
    
    
private MemCachedClient mcc;
    
    
private String name;
    
    
private String serverList;
    
    
private String weightList;
    
    
private int initConn = 10;;
    
    
private int minConn = 5;
    
    
private int maxConn = 50;
    
    
private long maxIdleTime = 1000 * 60 * 30;
    
    
private long maxBusyTime = 1000 * 60 * 5;
    
    
private long maintThreadSleep = 1000 * 5;
    
    
private int socketTimeOut = 1000 * 3;
    
    
private int socketConnectTO = 1000 * 3;
    
    
private boolean failover = false;
    
    
private boolean nagleAlg = false;
    
    
private boolean aliveCheck = false;

    
public void init() throws MemCachedException{
        
if(log.isDebugEnabled()) {
            log.debug(
"init socket pool.....");
        }

        
try{
            
if(null== pool || !pool.isInitialized()){
                pool 
= SockIOPool.getInstance(name);
                
                pool.setServers(StringUtils.split(serverList, 
','));
                String[] tmp 
= StringUtils.split(weightList, ',');
                Integer[] weights 
= new Integer[tmp.length];
                
                
for(int i = 0; i < tmp.length; ++i) {
                    weights[i] 
= NumberUtils.toInt(tmp[i], 0);
                }

                pool.setWeights(weights);
                pool.setInitConn(initConn);
                pool.setMinConn(minConn);
                pool.setMaxConn(maxConn);
                pool.setMaxIdle(maxIdleTime);
                pool.setMaxBusyTime(maxBusyTime);
                pool.setMaintSleep(maintThreadSleep);
                pool.setSocketConnectTO(socketConnectTO);
                pool.setSocketTO(socketTimeOut);
                pool.setNagle(nagleAlg);
                pool.setFailover(failover);
                pool.setAliveCheck(aliveCheck);
                pool.setHashingAlg( SockIOPool.NEW_COMPAT_HASH );
                pool.initialize();
            }

            
            
if(log.isDebugEnabled()) {
                log.debug(
"init socket pool.....done!");
                log.debug(
"create memcachedclient....");
            }

            
            mcc 
= new MemCachedClient();
            mcc.setCompressEnable(
false);
            mcc.setPoolName(name);
            
            
if(log.isDebugEnabled()) {
                log.debug(
"create memcachedclient....done!");
            }

        }
catch(Exception e){
            log.error(
"[初始化SocketPool异常=" + e.getMessage() + "]" );
            
throw new MemCachedException("初始化SocketPool异常");
        }

    }

    
    
public void destory() {
        
if(log.isDebugEnabled()) {
            log.debug(
"destory socket pool.....");
        }

        
if(null != pool)
            pool.shutDown();
        
if(log.isDebugEnabled()) {
            log.debug(
"destory socket pool.....done!");
        }


    }

    
    
    
public void set(String key, Object value, long expire) throws MemCachedException{
        
if(null == mcc)
            
throw new MemCachedException("MemCachedClient没有正常初始化");
        mcc.set(key, value, 
new Date(expire));
    }

    
    
public void set(String key, Object value) throws MemCachedException{
        set(key, value, HOUR);
    }

    
//    public void add(String key, Object value, long expire) {
//        mcc.add(key, value, new Date(expire));
//    }
    
    
    
public Object get(String key) throws MemCachedException{
        
if(null == mcc)
            
throw new MemCachedException("MemCachedClient没有正常初始化");
        
return mcc.get(key);
    }

    
    
    
public boolean containsKey(String key) {
        
if(null == mcc)
            
return false;
        
        
return mcc.keyExists(key);
    }

    
/**
     * 
@return the aliveCheck
     
*/

    
public boolean isAliveCheck() {
        
return aliveCheck;
    }


    
/**
     * 
@param aliveCheck the aliveCheck to set
     
*/

    
public void setAliveCheck(boolean aliveCheck) {
        
this.aliveCheck = aliveCheck;
    }


    
/**
     * 
@return the failover
     
*/

    
public boolean isFailover() {
        
return failover;
    }


    
/**
     * 
@param failover the failover to set
     
*/

    
public void setFailover(boolean failover) {
        
this.failover = failover;
    }


    
/**
     * 
@return the initConn
     
*/

    
public int getInitConn() {
        
return initConn;
    }


    
/**
     * 
@param initConn the initConn to set
     
*/

    
public void setInitConn(int initConn) {
        
this.initConn = initConn;
    }


    
/**
     * 
@return the maintThreadSleep
     
*/

    
public long getMaintThreadSleep() {
        
return maintThreadSleep;
    }


    
/**
     * 
@param maintThreadSleep the maintThreadSleep to set
     
*/

    
public void setMaintThreadSleep(long maintThreadSleep) {
        
this.maintThreadSleep = maintThreadSleep;
    }


    
/**
     * 
@return the maxBusyTime
     
*/

    
public long getMaxBusyTime() {
        
return maxBusyTime;
    }


    
/**
     * 
@param maxBusyTime the maxBusyTime to set
     
*/

    
public void setMaxBusyTime(long maxBusyTime) {
        
this.maxBusyTime = maxBusyTime;
    }


    
/**
     * 
@return the maxConn
     
*/

    
public int getMaxConn() {
        
return maxConn;
    }


    
/**
     * 
@param maxConn the maxConn to set
     
*/

    
public void setMaxConn(int maxConn) {
        
this.maxConn = maxConn;
    }


    
/**
     * 
@return the maxIdleTime
     
*/

    
public long getMaxIdleTime() {
        
return maxIdleTime;
    }


    
/**
     * 
@param maxIdleTime the maxIdleTime to set
     
*/

    
public void setMaxIdleTime(long maxIdleTime) {
        
this.maxIdleTime = maxIdleTime;
    }


    
/**
     * 
@return the minConn
     
*/

    
public int getMinConn() {
        
return minConn;
    }


    
/**
     * 
@param minConn the minConn to set
     
*/

    
public void setMinConn(int minConn) {
        
this.minConn = minConn;
    }


    
/**
     * 
@return the nagleAlg
     
*/

    
public boolean isNagleAlg() {
        
return nagleAlg;
    }


    
/**
     * 
@param nagleAlg the nagleAlg to set
     
*/

    
public void setNagleAlg(boolean nagleAlg) {
        
this.nagleAlg = nagleAlg;
    }


    
/**
     * 
@return the serverList
     
*/

    
public String getServerList() {
        
return serverList;
    }


    
/**
     * 
@param serverList the serverList to set
     
*/

    
public void setServerList(String serverList) {
        
this.serverList = serverList;
    }


    
/**
     * 
@return the socketConnectTO
     
*/

    
public int getSocketConnectTO() {
        
return socketConnectTO;
    }


    
/**
     * 
@param socketConnectTO the socketConnectTO to set
     
*/

    
public void setSocketConnectTO(int socketConnectTO) {
        
this.socketConnectTO = socketConnectTO;
    }


    
/**
     * 
@return the socketTimeOut
     
*/

    
public int getSocketTimeOut() {
        
return socketTimeOut;
    }


    
/**
     * 
@param socketTimeOut the socketTimeOut to set
     
*/

    
public void setSocketTimeOut(int socketTimeOut) {
        
this.socketTimeOut = socketTimeOut;
    }


    
/**
     * 
@return the weightList
     
*/

    
public String getWeightList() {
        
return weightList;
    }


    
/**
     * 
@param weightList the weightList to set
     
*/

    
public void setWeightList(String weightList) {
        
this.weightList = weightList;
    }


    
/**
     * 
@return the name
     
*/

    
public String getName() {
        
return name;
    }


    
/**
     * 
@param name the name to set
     
*/

    
public void setName(String name) {
        
this.name = name;
    }


}

其中MemCachedException为自定义异常。必须注意到一个MemCachedClient在能使用前必须正确初始化SocketIOPool,在使用完成后必须关闭所有的Pool。
在将一个对象放入到MemCache的时候可以设定一个过期时间,这个参数是Date型的,这里可能产生一点迷惑,是否指定准确的过期日期?其实不是,如果我们想对象在10秒后过期,这个参数就直接new Date(10000)就可以了,但是必须大于1秒,因为MemCache内部处理Java实现是expiry.getTime()/1000,如果小于1秒,这个参数会被处理为0,也就是永远不过期。
MemCache有2个方法可以添加对象,set()和add()。对于没有放入过的Key,这2个方法并无区别,但是对于已经放入过的Key,add()不起任何作用,set()则会刷新对象内容和过期时间
采用Spring注入
    <bean id="memCachedClient" class="com.xxx.xxx.memcached.MemCachedClientWrapper" 
        init-method
="init" destroy-method="destory">
        
<property name="name">
            
<value>test</value>
        
</property>
        
<property name="serverList">
            
<value>10.2.2.212:11211</value>    
        
</property>
        
<property name="weightList">
            
<value>5</value>    
        
</property>
        
<property name="initConn">
            
<value>5</value>    
        
</property>
        
<property name="minConn">
            
<value>5</value>    
        
</property>
        
<property name="maxConn">
            
<value>20</value>    
        
</property>                        
    
</bean>
原创粉丝点击