Windows下java memcached 使用

一,Memcached介绍

memcached是被广泛使用的分布式缓存技术,使用它的目的是,通过它缓存数据库查询结果,减少数据库访问次数,提高动态Web应用的速度。
memcached作为分布式缓存服务器,具有如下的特点:
(1)协议简单:
memcached的服务器和客户端使用的通信协议是简单的基于文本行的协议,因此我们可以通过telnet也能在memcached服务器上保存/获取数据,如下:
这里写图片描述

这里写图片描述
(2)基于libevent的事件处理:
libevent是个程序库,memcached通过libevent能在linux、BSD等操作系统上发挥其高性能的特性。
(3)内置内存存储方式:
为了提高性能,memcached将数据保存在其内置的内存存储空间里,同样也是因为如此,所以当memcached重启、重启操作系统等操作会导致memcached存储的数据丢失。
另外,当内容的容量达到指定的值后,memcached会使用LRU算法自动删除不使用的缓存,以释放空间。
(4)memcached不互相通信的分布式:
经常说到memcached是分布式的缓存技术,但是它的分布式不是指服务器端的分布式,因为服务器端并没有分布式的功能。它的分布式是通过客户端来实现的,见下图
这里写图片描述

二,Windows下memcached的使用

1, 用到的jar包
这里写图片描述

其中Memcached-Java-Client-3.0.0.jar为memcached客户端,jar和源码下载地址http://search.maven.org/

2, 部分代码

public class MemcachedTest {

    protected static MemCachedClient mcc = new MemCachedClient();
    protected static MemcachedTest memcachedTest = new MemcachedTest();

    //设置与memcached服务器的连接信息
    static{
        /// 服务器列表和其权重
        String [] servers  = {"127.0.0.1:11211","192.168.0.101:11211"};
        Integer [] weights = {5,5};

        // 获取sock连接池的实例对象
        SockIOPool pool = SockIOPool.getInstance();

        pool.setServers(servers);
        pool.setWeights(weights);

        // 设置初始连接数、最小和最大连接数以及最大处理时间
        pool.setInitConn(5);
        pool.setMinConn(5);
        pool.setMaxConn(100);
        pool.setMaxIdle(1000*60*60*6);

        // 设置主线程的睡眠时间
        pool.setMaintSleep(30);

        // 设置TCP的参数,连接超时等
        pool.setNagle(false);
        pool.setSocketTO(3000);
        pool.setSocketConnectTO(0);

        pool.setHashingAlg(SockIOPool.CONSISTENT_HASH);

        // 初始化连接池
        pool.initialize();

    }

    /**
     * 保护型构造方法,不允许实例化!
     * 
     */
    protected MemcachedTest() {

    }

    /**
     * 获取唯一实例.
     * 
     * @return
     */
    public static MemcachedTest getInstance() {
        return memcachedTest;
    }

    /**
     * 添加数据
     * @param key
     * @param value
     * @return
     */
    public boolean add(String key, String value){
        return mcc.add(key, value);
    }

    public boolean add(String key, String value, Date expiry){
        return mcc.add(key, value, expiry);
    }

    public boolean replace(String key, String value){
        return mcc.replace(key,value);
    }

    public boolean replace(String key, String value, Date expiry){
        return mcc.replace(key, value, expiry);
    }

    public Object get(String key){
        return mcc.get(key);
    }

    public Object flush(){
        return mcc.flushAll();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MemcachedTest mt = MemcachedTest.getInstance();
        mt.flush();
        for (int i = 0; i < 10; i ++){
            mt.add("hello"+ i, "world" + i);
        }
        for(int i = 0; i < 10; i ++){
            System.out.println("the value of key Hello" + i +" is: " + mt.get("hello" + i));
        }
    }

}

首先,我们需要一个memcachedClient对象,该对象实现将数据添加到memcached服务器或者从服务器读取数据。然后初始化一个SockIOPool对象,该对象用来维护一个到memcached服务器的持续的连接池,连接池必须在使用前初始化。

3, memcached Client源码解读

在将数据添加到服务器这个过程,主要涉及到了客户端的下面的几个类:
MemCachedClient:生成客户端的入口
AscIIClient: memcachedClient的子类,负责具体的client的实例化
SchoonerSockIOPool
SockIOPool

(1) 初始化一个memcached client对象
protected static MemCachedClient mcc = new MemCachedClient();
查看client的源码发现它会通过解析参数,生成一个子类AscIIClient的对象。

    /**
     * Creates a new instance of MemCachedClient.
     */
    public MemCachedClient() {
        this(null, true, false);
    }

    /**
     * Create memcached client.
     * 
     * @param poolName
     *            name of SockIOPool
     * @param isTCP
     *            use tcp protocol
     * @param binaryProtocal
     *            use binary protocol.
     */
     public MemCachedClient(String poolName, boolean isTcp, boolean binaryProtocal) {
        if (binaryProtocal)
            client = new BinaryClient(poolName);
        else
            client = isTcp ? new AscIIClient(poolName) : new AscIIUDPClient(poolName);
    }

(2)在子类AscIIClient中,定义了一个pool的实例如下:

// pool instance
    private SchoonerSockIOPool pool;

根据上面第一点,在生成memcached client实例时,其实实际上生成的AscIIClient的实例,如下:

/**
     * Creates a new instance of MemCachedClient accepting a passed in pool
     * name.
     * 
     * @param poolName
     *            name of SockIOPool
     * @param binaryProtocal
     *            whether use binary protocol.
     */
    public AscIIClient(String poolName) {
        super((MemCachedClient) null);
        this.poolName = poolName;
        init();
    }

其中init()方法主要是完成一个默认的(default)client的初始化。

/**
     * Initializes client object to defaults.
     * 
     * This enables compression and sets compression threshhold to 15 KB.
     */
    private void init() {
        this.sanitizeKeys = true;
        this.primitiveAsString = false;
        this.compressEnable = false;
        this.compressThreshold = COMPRESS_THRESH;
        this.defaultEncoding = "UTF-8";
        this.poolName = (this.poolName == null) ? "default" : this.poolName;

        // get a pool instance to work with for the life of this instance
        this.pool = SchoonerSockIOPool.getInstance(poolName);
    }

(3)SockIOPool和SchoonerSockIOPool的关系:
在SockIOPool中,定义了一个SchoonerSockIOPool的实例,在初始化SockIOPool的时候,同时会获取一个SchoonerSockIOPool的对象。

// 获取sock连接池的实例对象
        SockIOPool pool = SockIOPool.getInstance();
/**
     * Single argument version of factory used for back compat. Simply creates a
     * pool named "default".
     * 
     * @return instance of SockIOPool
     */
    public static SockIOPool getInstance() {
        SockIOPool whalinSockIOPool = new SockIOPool();
        whalinSockIOPool.schoonerSockIOPool = SchoonerSockIOPool.getInstance("default");
        return whalinSockIOPool;
    }

(4) 通过SchoonerSockIOPool.getInstance方法获取一个SchoonerSockIOPool的实例时,程序会先检查连接池里面是否有名称为“default”的pool,若有,则取处理返回; 若无,生成名称为“default”的pool,并将该pool放置到连接池里面。

/**
     * Factory to create/retrieve new pools given a unique poolName.
     * 
     * @param poolName
     *            unique name of the pool
     * @return instance of SockIOPool
     */
    public static SchoonerSockIOPool getInstance(String poolName) {
        SchoonerSockIOPool pool;

        synchronized (pools) {
            if (!pools.containsKey(poolName)) {
                pool = new SchoonerSockIOPool(true);
                pools.putIfAbsent(poolName, pool);
            }
        }

        return pools.get(poolName);
    }

未完待续……

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值