memcached缓存


    什么是缓存

        凡是位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之为缓存

    分类

            操作系统磁盘缓存,减少磁盘机械操作
            数据库缓存,减少文件系统IO
            应用程序缓存,减少数据库操作
            WEB服务器缓存,减少应用服务器请求
            客户端浏览器缓存,减少网站访问

    web相关

            数据库缓存
            系统配置参数缓存
            ORM提供的对象缓存、查询缓存
            缓存服务器 EHCache、OSCache、JBossCache
            通用缓存 memcached、radis
            页面缓存(动态页面静态化、Servlet缓存、页面局部缓存)
            ajax查询结果缓存
            浏览器缓存
            代理服务器缓存
            CDN加速

    适用范围

        频繁访问且时效性不高的数据。例如:用户信息、菜单权限、功能权限、历史数据查询等

    memcached缓存

        Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。[http://baike.baidu.com/view/794242.htm]

    alisoft Memcached Client

        尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息。那么,怎样进行分布式呢?这完全取决于客户端的实现。所以,alisoft Memcached Client是一个支持分布式集群的管理客户端。

    单客户端配置

<?xml version="1.0" encoding="UTF-8"?>
<memcached>
    <client name="mclient0" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool0">
        <errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
    </client>
    <socketpool name="pool0" failover="true" initConn="5" minConn="5" maxConn="250" maintSleep="5000" nagle="false"
        socketTO="3000" aliveCheck="true">
        <servers>127.0.0.1:11211,127.0.0.1:11212</servers>
        <weights>3,7</weights>
    </socketpool>
</memcached>

   
    创建memcached的标签

    创建 client的标签

        name 属性是程序中使用Cache的唯一标识。
        socketpool 属性将会关联到后面的socketpool配置。
        errorHandler 可选,用来处理出错情况。注意在Tag中不要使用空格或者Tab键。

        创建socketpool的标签

            name 属性和client 配置中的socketpool 属性相关联。
            maintSleep属性是后台线程管理SocketIO池的检查间隔时间,如果设置为0,则表明不需要后台线程维护SocketIO线程池,默认需要管理。
            socketTO 属性是Socket操作超时配置,单位ms。
            aliveCheck 属性表示在使用Socket以前是否先检查Socket状态。

        创建 servers 标签作为socketPool的子标签.设置memcache服务端实例地址,支持多个地址设置,例如“127.0.0.1:11211” 或 “127.0.0.1:11211, 127.0.0.1:11212”

        创建 weights 标签作为socketPool的子标签(可选),它表明了上面设置的服务器实例的Load权重. 例如 <weights>3,7</weights>表示30% load 在 127.0.0.1:11211, 70% load 在 127.0.0.1:11212
            单客户端代码

/**
 * lincl
 * 2016年7月12日 下午4:56:35
 * 
 */
package com.lezic.core.cache.memcached;

import java.util.Calendar;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.alisoft.xplatform.asf.cache.ICacheManager;
import com.alisoft.xplatform.asf.cache.IMemcachedCache;
import com.alisoft.xplatform.asf.cache.memcached.CacheUtil;
import com.alisoft.xplatform.asf.cache.memcached.MemcachedCacheManager;

/**
 * 单客户端
 * 
 * @author lincl
 * 
 */
public class MemcachedClient {
    static ICacheManager<IMemcachedCache> manager;

    /**
     * 初始化上下文,加载配置文件
     * 
     * @throws Exception
     */
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        manager = CacheUtil.getCacheManager(IMemcachedCache.class, MemcachedCacheManager.class.getName());
        manager.setConfigFile("memcached0.xml");
        manager.setResponseStatInterval(5 * 1000);
        manager.start();
    }

    /**
     * 摧毁管理器
     * 
     * @throws java.lang.Exception
     */
    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        manager.stop();
    }

    /**
     * 测试获取
     * 
     */
    @Test
    public void testGet() {
        try {
            IMemcachedCache cache = manager.getCache("mclient0");
            cache.remove("key1");
            cache.remove("key2你好");
            cache.put("key1", "1");
            cache.put("key2你好", "你好123");
            Assert.assertEquals(cache.get("key1"), "1");
            Assert.assertEquals(cache.get("key2你好"), "你好123");
        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.assertTrue(false);
        }
    }

    /**
     * 测试删除
     */
    @Test
    public void testRemove() {
        try {
            IMemcachedCache cache = manager.getCache("mclient0");
            cache.remove("key1");
            cache.put("key1", "value1");
            Assert.assertEquals(cache.get("key1"), "value1");
            cache.remove("key1");
            Assert.assertNull(cache.get("key1"));
        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.assertTrue(false);
        }
    }

    /**
     * 测试是否包含key
     */
    @Test
    public void testContainsKey() {
        try {
            IMemcachedCache cache = manager.getCache("mclient0");
            cache.remove("key1");
            cache.put("key1", "value1");
            Assert.assertTrue(cache.containsKey("key1"));
        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.assertTrue(false);
        }
    }

    @Test
    public void testAdd() {
        try {
            IMemcachedCache cache = manager.getCache("mclient0");
            cache.remove("key1");
            Assert.assertTrue(cache.add("key1", "value1"));
            Assert.assertFalse(cache.add("key1", "value1"));
            Assert.assertEquals(cache.get("key1"), "value1");
            cache.remove("key1");
        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.assertTrue(false);
        }
    }

    /**
     * Test method for {@link com.alisoft.xplatform.asf.cache.ICache#clear()}.
     */
    @Test
    public void testClear() {
        try {
            IMemcachedCache cache = manager.getCache("mclient0");
            cache.remove("key1");
            cache.put("key1", "value1");
            Assert.assertEquals(cache.get("key1"), "value1");
            cache.clear();
            Assert.assertNull(cache.get("key1"));
            Thread.sleep(2000);
        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.assertTrue(false);
        }
    }

    /**
     * 保存有有效期的数据 Test method for
     * {@link com.alisoft.xplatform.asf.cache.ICache#put(java.lang.Object, java.lang.Object, java.util.Date)} .
     */
    @Test
    public void testPutKVDate() {
        try {
            IMemcachedCache cache = manager.getCache("mclient0");
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.SECOND, 5);
            cache.remove("key1");
            cache.put("key1", "value1", calendar.getTime());
            Assert.assertEquals(cache.get("key1"), "value1");
            Thread.sleep(5 * 1000 + 1000);
            Assert.assertNull(cache.get("key1"));
        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.assertTrue(false);
        }
    }
}

    

9.集群配置

<?xml version="1.0" encoding="UTF-8"?>
<memcached>

    <client name="mclient" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool0">
        <errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
    </client>

    <client name="mclient1" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool1">
        <errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
    </client>

    <client name="mclient2" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool2">
        <errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
    </client>

    <client name="mclient3" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool3">
        <errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
    </client>

    <client name="mclient4" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool4">
        <errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
    </client>


    <socketpool name="pool0" failover="true" initConn="5" minConn="5" maxConn="250" maintSleep="0" nagle="false"
        socketTO="3000" aliveCheck="true">
        <servers>127.0.0.1:11210</servers>
    </socketpool>

    <socketpool name="pool1" failover="true" initConn="5" minConn="5" maxConn="250" maintSleep="0" nagle="false"
        socketTO="3000" aliveCheck="true">
        <servers>127.0.0.1:11211</servers>
    </socketpool>

    <socketpool name="pool2" failover="true" initConn="5" minConn="5" maxConn="250" maintSleep="0" nagle="false"
        socketTO="3000" aliveCheck="true">
        <servers>127.0.0.1:11212</servers>
    </socketpool>

    <socketpool name="pool3" failover="true" initConn="5" minConn="5" maxConn="250" maintSleep="0" nagle="false"
        socketTO="3000" aliveCheck="true">
        <servers>127.0.0.1:11213</servers>
    </socketpool>

    <socketpool name="pool4" failover="true" initConn="5" minConn="5" maxConn="250" maintSleep="0" nagle="false"
        socketTO="3000" aliveCheck="true">
        <servers>127.0.0.1:11214</servers>
    </socketpool>

    <cluster name="cluster1" mode="active">
        //mode = active,standby
        <memCachedClients>mclient1,mclient2</memCachedClients>
    </cluster>

    <cluster name="cluster2" mode="standby">
        //mode = active,standby
        <memCachedClients>mclient3,mclient4</memCachedClients>
    </cluster>

</memcached>

   
    创建cluster标签
    创建memCachedClients

        标签作为cluster的子标签,然后将客户端配置到memCachedClients 标签中

    可以配置cluster mode(如果没有设置mode属性,默认采用active)

    集群当前的特性

            集群中多节点软负载均衡。(当前采用简单的Hash算法加取余来分发数据)
            数据在多节点上异步冗余存储。(防止数据丢失最基本要求)
            节点不可用切换功能。(当根据算法分发到某一失败节点时可以转向到其他可用节点)
            节点恢复可用后数据Lazy复制。(当A,B两台机器作为集群的时候,如果A出现了问题,系统会去B获取数据,当A正常以后,如果应用在A中没有拿到数据可以去B获取数据,并且复制到A上,这种方式也是一种lazy的复制。)

        集群代码

/**
 * 
 */
package com.alisoft.xplatform.asf.cache;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

import com.alisoft.xplatform.asf.cache.memcached.CacheUtil;
import com.alisoft.xplatform.asf.cache.memcached.MemcachedCacheManager;

/**
 * 集群测试类
 * @author wenchu.cenwc
 * 
 */
public class MemcachedClusterTest {

    static ICacheManager<IMemcachedCache> manager;

    /**
     * @throws java.lang.Exception
     */
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        manager = CacheUtil.getCacheManager(IMemcachedCache.class, MemcachedCacheManager.class.getName());
        manager.setConfigFile("memcached_cluster.xml");
        manager.start();
    }

    /**
     * @throws java.lang.Exception
     */
    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        manager.stop();
    }

    @Test
    public void testActiveMode() {
        try {
            IMemcachedCache cache1 = manager.getCache("mclient1");
            IMemcachedCache cache2 = manager.getCache("mclient2");

            cache1.put("key1", "value1");
            cache1.put("key2", "value2");
            cache1.put("key3", "value3");
            cache1.put("key4", "value4");
            cache1.put("key5", "value5");
            cache1.put("key6", "value6");

            // 模拟mclient1失效(结束服务端),有出错日志在控制台打印
            Assert.assertEquals(cache1.get("key1"), "value1");
            Assert.assertEquals(cache1.get("key2"), "value2");
            Assert.assertEquals(cache1.get("key3"), "value3");
            Assert.assertEquals(cache1.get("key4"), "value4");
            Assert.assertEquals(cache1.get("key5"), "value5");
            Assert.assertEquals(cache1.get("key6"), "value6");

            Assert.assertEquals(cache2.get("key1"), "value1");
            Assert.assertEquals(cache2.get("key2"), "value2");
            Assert.assertEquals(cache2.get("key3"), "value3");
            Assert.assertEquals(cache2.get("key4"), "value4");
            Assert.assertEquals(cache2.get("key5"), "value5");
            Assert.assertEquals(cache2.get("key6"), "value6");

            // 恢复mclient1,无出错日志在控制台打印
            Assert.assertEquals(cache1.get("key1"), "value1");
            Assert.assertEquals(cache1.get("key2"), "value2");
            Assert.assertEquals(cache1.get("key3"), "value3");
            Assert.assertEquals(cache1.get("key4"), "value4");
            Assert.assertEquals(cache1.get("key5"), "value5");
            Assert.assertEquals(cache1.get("key6"), "value6");

            Assert.assertEquals(cache2.get("key1"), "value1");
            Assert.assertEquals(cache2.get("key2"), "value2");
            Assert.assertEquals(cache2.get("key3"), "value3");
            Assert.assertEquals(cache2.get("key4"), "value4");
            Assert.assertEquals(cache2.get("key5"), "value5");
            Assert.assertEquals(cache2.get("key6"), "value6");

        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.assertTrue(false);
        }
    }

    @Test
    @Ignore
    public void testStandByMode() {
        IMemcachedCache cache1 = manager.getCache("mclient3");
        IMemcachedCache cache2 = manager.getCache("mclient4");

        cache1.put("key1", "value1");
        cache1.put("key2", "value2");
        cache1.put("key3", "value3");
        cache1.put("key4", "value4");
        cache1.put("key5", "value5");
        cache1.put("key6", "value6");

        // 模拟mclient1失效(结束服务端),有出错日志在控制台打印
        Assert.assertEquals(cache1.get("key1"), "value1");
        Assert.assertEquals(cache1.get("key2"), "value2");
        Assert.assertEquals(cache1.get("key3"), "value3");
        Assert.assertEquals(cache1.get("key4"), "value4");
        Assert.assertEquals(cache1.get("key5"), "value5");
        Assert.assertEquals(cache1.get("key6"), "value6");

        Assert.assertEquals(cache2.get("key1"), "value1");
        Assert.assertEquals(cache2.get("key2"), "value2");
        Assert.assertEquals(cache2.get("key3"), "value3");
        Assert.assertEquals(cache2.get("key4"), "value4");
        Assert.assertEquals(cache2.get("key5"), "value5");
        Assert.assertEquals(cache2.get("key6"), "value6");

        // 恢复mclient1,无出错日志在控制台打印
        Assert.assertNull(cache1.get("key1"));
        Assert.assertEquals(cache1.get("key2"), "value2");
        Assert.assertNull(cache1.get("key3"));
        Assert.assertEquals(cache1.get("key4"), "value4");
        Assert.assertNull(cache1.get("key5"));
        Assert.assertEquals(cache1.get("key6"), "value6");

        Assert.assertNull(cache2.get("key1"));
        Assert.assertEquals(cache2.get("key2"), "value2");
        Assert.assertNull(cache2.get("key3"));
        Assert.assertEquals(cache2.get("key4"), "value4");
        Assert.assertNull(cache2.get("key5"));
        Assert.assertEquals(cache2.get("key6"), "value6");
    }

    /**
     * 集群复制
     * 
     */
    @Test
    public void testClusterCopy() {
        try {
            IMemcachedCache cache = manager.getCache("mclient");
            IMemcachedCache cache1 = manager.getCache("mclient1");
            IMemcachedCache cache2 = manager.getCache("mclient2");

            cache.put("key1", "value1");
            cache.put("key2", "value2");
            cache.put("key3", "value3");
            cache.put("key4", "value4");
            cache.put("key5", "value5");
            cache.put("key6", "value6");

            cache1.remove("key1");
            cache1.remove("key2");
            cache1.remove("key3");
            cache1.remove("key4");
            cache1.remove("key5");
            cache1.remove("key6");

            cache2.remove("key1");
            cache2.remove("key2");
            cache2.remove("key3");
            cache2.remove("key4");
            cache2.remove("key5");
            cache2.remove("key6");

            manager.clusterCopy("mclient", "cluster1");

            Assert.assertEquals(cache1.get("key1"), "value1");
            Assert.assertEquals(cache1.get("key2"), "value2");
            Assert.assertEquals(cache1.get("key3"), "value3");
            Assert.assertEquals(cache1.get("key4"), "value4");
            Assert.assertEquals(cache1.get("key5"), "value5");
            Assert.assertEquals(cache1.get("key6"), "value6");

            Assert.assertEquals(cache2.get("key1"), "value1");
            Assert.assertEquals(cache2.get("key2"), "value2");
            Assert.assertEquals(cache2.get("key3"), "value3");
            Assert.assertEquals(cache2.get("key4"), "value4");
            Assert.assertEquals(cache2.get("key5"), "value5");
            Assert.assertEquals(cache2.get("key6"), "value6");

        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.assertTrue(false);
        }
    }

    @Test
    public void testReload() {
        try {
            IMemcachedCache cache = manager.getCache("mclient");
            IMemcachedCache cache1 = manager.getCache("mclient1");
            IMemcachedCache cache2 = manager.getCache("mclient2");
            IMemcachedCache cache5 = manager.getCache("mclient5");
            IMemcachedCache cache6 = manager.getCache("mclient6");

            Assert.assertNull(cache5);
            Assert.assertNull(cache6);

            cache.clear();
            Thread.sleep(1000);
            cache1.clear();
            Thread.sleep(1000);
            cache2.clear();
            Thread.sleep(1000);

            cache.put("key1", "1");
            cache1.put("key2", "2");

            Assert.assertNull(cache.get("key2"));
            Assert.assertNull(cache1.get("key1"));

            Thread.sleep(2000);

            // manager.reload("http://10.2.226.41/sip/memcached_cluster2.xml");
            manager.reload("memcached_cluster2.xml");

            Thread.sleep(2000);

            cache1 = manager.getCache("mclient1");
            cache2 = manager.getCache("mclient2");
            cache5 = manager.getCache("mclient5");
            cache6 = manager.getCache("mclient6");

            Assert.assertNull(cache1);
            Assert.assertNull(cache2);
            Assert.assertNotNull(cache5);
            Assert.assertNotNull(cache6);

            cache5.clear();
            Thread.sleep(1000);
            cache6.clear();
            Thread.sleep(3000);

            manager.reload("memcached_cluster3.xml");

            Thread.sleep(2000);

            cache = manager.getCache("mclient");
            cache1 = manager.getCache("mclient1");
            cache2 = manager.getCache("mclient2");
            cache5 = manager.getCache("mclient5");
            cache6 = manager.getCache("mclient6");

            Assert.assertEquals(cache.get("key2"), "2");
            Assert.assertEquals(cache1.get("key1"), "1");

            Assert.assertEquals(cache2.get("key2"), "2");
            Assert.assertEquals(cache5.get("key2"), "2");
            Assert.assertNull(cache2.get("key1"));
            Assert.assertNull(cache5.get("key1"));
            Assert.assertNull(cache6.get("key1"));
            Assert.assertNull(cache6.get("key2"));

        } catch (Exception ex) {
            ex.printStackTrace();
            Assert.assertTrue(false);
        }
    }

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值