打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Xmemcached使用【二】

Xmemcached的Wiki:http://code.google.com/p/xmemcached/wiki/User_Guide_zh#与Hibernate-memcached集成

一、软件环境

     1memcached-1.4.5

     2xmemcached-1.4.1

二、简单示例

    1、设置节点权重

        如果需要编程设置,通过下面代码:

 MemcachedClientBuilder builder = new    

 XMemcachedClientBuilder(AddrUtil.getAddresses("localhost:12000 localhost:12001"),new int[]{1,3});

 MemcachedClient memcachedClient=builder.build();

传入一个int数组,里面的元素就是节点对应的权重值,比如这里设置"localhost:12000"节点的权重为1,而"localhost:12001"的权重为3。注意,xmemcached的权重是通过复制连接的多个引用来实现的,比如权重为3,那么就复制3个同一个连接的引用放在集合中让MemcachedSessionLocator查找。

 

改变节点权重,可以通过setServerWeight方法:

public interface XMemcachedClientMBean{

             ....

         /**

         * Set a memcached server's weight

         *

         * @param server

         * @param weight

         */

        public void setServerWeight(String server, int weight);

   }

    2、使用二进制协议

       Memcached 1.4开始正式启用二进制协议,xmemcached 1.2开始支持二进制协议,启用这一特性也非常简单,设置相应的CommandFactory即可:

    MemcachedClientBuilder builder = new    XMemcachedClientBuilder(AddrUtil.getAddresses("localhost:12000 localhost:12001"),new int[]{1,3});

  builder.setCommandFactory(new BinaryCommandFactory());//use binary protocol

  MemcachedClient memcachedClient=builder.build();

    3、动态添加/删除节点

       MemcachedClient client=new XMemcachedClient(AddrUtil.getAddresses("server1:11211 server2:11211"));

   //Add two new memcached nodes

   client.addServer("server3:11211 server4:11211");

   //Remove memcached servers

   client.removeServer("server1:11211 server2:11211");

    4NIO连接池

        Xmemcached是基于java nio的client实现,默认对一个memcached节点只有一个连接,这在通常情况下已经有非常优异的表现。但是在典型的高并发环境下,nio的  单连接也会遇到性能瓶颈。因此XMemcached支持设置nio的连接池,允许建立多个连接到同一个memcached节点,但是请注意,这些连接之间是不同步的,因此你的应用需要自己保证数据更新的同步,启用连接池可以通过下面代码:

MemcachedClientBuilder builder = new    XMemcachedClientBuilder(AddrUtil.getAddresses("localhost:12000"));

builder.setConnectionPoolSize(5);

    5Failure模式和standby节点

从1.3版本开始,xmemcached支持failure模式。所谓failure模式是指,当一个memcached节点down掉的时候,发往这个节点的请求将直接失败,而不是发送给下一个有效的memcached节点。具体可以看memcached的文档。默认不启用failure模式,启用failure模式可以通过下列代码:MemcachedClientBuilder builder=…… builder.setFailureMode(true);

不仅如此,xmemcached还支持主辅模式,你可以设置一个memcached的节点的备份节点,当主节点down掉的情况下,会将本来应该发往主节点的请求转发给standby备份节点。使用备份节点的前提是启用failure模式。备份节点设置如下:MemcachedClient builder=new XmemcachedClientBuilder(AddrUtil.getAddressMap("localhost:11211,localhost:11212 host2:11211,host2:11212"));

 

    6与Kestrel交互

       Kestrel是twitter开源的一个scala写的简单高效MQ,它支持 memcached文本协议,但是并不完全兼容,例如它不支持flag,导致很多利用flag做序列化的客户端无法正常运作。因此Xmemcached特意提供了KestrelCommandFactory?用于支持Kestrel。使用KestrelCommandFactory?即可拥有如下好处:默认关闭get优化,因为kestrel不支持bulk get;支持kestrel的阻塞获取和可靠获取;允许向kestrel存储任意java序列化类型。设置KestrelCommandFactory:

MemcachedClientBuilder builder = new    XMemcachedClientBuilder(AddrUtil.getAddresses("localhost:12000 localhost:12001"),new int[]{1,3});

builder.setCommandFactory(new KestrelCommandFactory());

MemcachedClient memcachedClient=builder.build();

 

关于最后一点需要补充说明,由于kestrel不支持flag,因此xmemcached在存储的数据之前加了4个字节的flag,如果你的全部应用都使用xmemcached,那么没有问题,如果使用其他clients,会有兼容性的问题,因此Xmemcached还允许关闭这个功能,通过client.setPrimitiveAsString(true);设置为true后,原生类型都将存储为字符串,而序列化类型将无法存储了。

 

    7与tokyotyrant交互

       通过使用TokyoTyrantTranscoder就可以跟TokyoTyrant进行交互,但是由于TokyoTyrant对memcached文本协议的flag,exptime不支持,因此内部TokyoTyrantTranscoder加了4个字节的flag在value前面,如果你的全部应用都使用xmemcached,那么没有问题,如果使用其他clients,会有兼容性的问题,这一点与跟kestrel交互相同。

MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses("localhost:12000 localhost:12001"),new int[]{1,3});

builder.setTranscoder(new TokyoTyrantTranscoder());

MemcachedClient memcachedClient=builder.build();

    8数据压缩

        memcached存储大数据的效率是比较低的,当数据比较大的时候xmemcached会帮你压缩在存储,取出来的时候自动解压并反序列化,这个大小阀值默认是16K,可以通过Transcoder接口的setCompressionThreshold(1.2.1引入)方法修改阀值,比如设置为1K:memcachedClient.getTranscoder()).setCompressionThreshold(1024);

    9packZeros

         XMemcached的序列化转换器在序列化数值类型的时候有个特殊处理,如果前面N个字节都是0,那么将会去除这些0,缩减后的数据将更小,例如数字3序列化是0x0003,那么前面3个0将去除掉成一个字节0x3。反序列化的时候将自动在前面根据数值类型补0。这一特性默认是开启的,如果考虑到与其他client兼容的话需要关闭此特性可以通过:memcachedClient.getTranscoder()).setPackZeros(false);

    10sanitizeKey    

         在官方客户端有提供一个sanitizeKeys选项,当选择用URL当key的时候,MemcachedClient会自动将URL encode再存储。默认是关闭的,想启用可以通过:   

         memcachedClient.setSanitizeKeys(true);

 

配置选项参数表:

属性名

servers

memcached节点列表,形如“主节点1:port,备份节点1:port 主节点2:port,备份节点2:port“的字符串,可以不设置备份节点,主备节点逗号隔开,不同分组空格隔开。

weights

servers对应的节点的权重

authInfoMap

授权验证信息,仅在xmemcached 1.2.5及以上版本有效

connectionPoolSize

nio连接池大小,默认为1

commandFactory

协议工厂,net.rubyeye.xmemcached.command.BinaryCommandFactory,TextCommandFactory(默认),KestrelCommandFactory

sessionLocator

分布策略,一致性哈希net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator或者ArraySessionLocator(默认)

 

transcoder

序列化转换器,默认使用net.rubyeye.xmemcached.transcoders.SerializingTranscoder,更多选项参见javadoc

bufferAllocator

IoBuffer分配器,默认为net.rubyeye.xmemcached.buffer.SimpleBufferAllocator,可选CachedBufferAllocator(不推荐)

failureMode

是否启用failure模式,true为启用,默认不启用

 完整代码示例

memcached.properties

Html代码  
  1. #127.0.0.1:11211 127.0.0.1:11212   
  2. addressList=127.0.0.1:11211 127.0.0.1:11212 127.0.0.1:11213 127.0.0.1:11214  
  3. weights=1,2,3,4  
  4. #1-30  
  5. connectionPoolSize=15  
  6. failureMode=true  
  7. #----------------------------------------------------------------------------------------------------------------#  
  8. #连接池大小即客户端个数  
  9. memcached.connectionPoolSize=5  
  10. memcached.failureMode=true  
  11. #server1  
  12. memcached.server1.host=127.0.0.1  
  13. memcached.server1.port=11211  
  14. memcached.server1.weight=4  
  15. #server2  
  16. memcached.server2.host=127.0.0.1  
  17. memcached.server2.port=11212  
  18. memcached.server2.weight=3                
  19. #server3  
  20. memcached.server3.host=127.0.0.1  
  21. memcached.server3.port=11213  
  22. memcached.server3.weight=2                    
  23. #server4  
  24. memcached.server4.host=127.0.0.1  
  25. memcached.server4.port=11214  
  26. memcached.server4.weight=1         
  27.   
  28.    

如果配置主备,需要修改 addressList

Html代码  
  1. addressList=127.0.0.1:11211,127.0.0.1:11212 127.0.0.1:11213,127.0.0.1:11214  

 

XmemcachedUtil.java

Java代码  
  1. package com.wy.util;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.Properties;  
  5.   
  6. import org.slf4j.Logger;  
  7. import org.slf4j.LoggerFactory;  
  8. import com.google.code.yanf4j.util.ResourcesUtils;  
  9.   
  10. import net.rubyeye.xmemcached.MemcachedClient;  
  11. import net.rubyeye.xmemcached.MemcachedClientBuilder;  
  12. import net.rubyeye.xmemcached.XMemcachedClientBuilder;  
  13. import net.rubyeye.xmemcached.auth.AuthInfo;  
  14. import net.rubyeye.xmemcached.command.BinaryCommandFactory;  
  15. import net.rubyeye.xmemcached.impl.ElectionMemcachedSessionLocator;  
  16. import net.rubyeye.xmemcached.utils.AddrUtil;  
  17.   
  18. /** 
  19.  * Xmemcached工具类 
  20.  *  
  21.  * @author wy 
  22.  * @serial 2013-08-12 
  23.  */  
  24. public class XmemcachedUtil {  
  25.     private static Logger log = LoggerFactory.getLogger(XmemcachedUtil.class);  
  26.     private static MemcachedClientBuilder builder = null;  
  27.     private static MemcachedClient memcacheddClient = null;  
  28.     private static Properties prop = null;  
  29.       
  30.     static {  
  31.         try {  
  32.             prop = ResourcesUtils.getResourceAsProperties("memcached.properties");  
  33.         } catch (IOException e) {  
  34.             e.printStackTrace();  
  35.             log.error("请配置memcached服务地址!");  
  36.         }  
  37.         if(prop != null){  
  38.             String addrs = prop.getProperty("addressList");  
  39.             String weight = prop.getProperty("weights");  
  40.             if(weight != null){  
  41.                 String[] weightsArray = weight.split(",");  
  42.                 int len = weightsArray.length;  
  43.                 int[] weights = new int[len];  
  44.                 for(int i=0;i<len;i++){  
  45.                     weights[i] = Integer.parseInt(weightsArray[i]);  
  46.                 }  
  47.                 //builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(addrs), weights);  
  48.                 //standby 主备模式  
  49.                 builder = new XMemcachedClientBuilder(AddrUtil.getAddressMap(addrs), weights);  
  50.             }else{  
  51.                 builder = new XMemcachedClientBuilder(AddrUtil.getAddressMap(addrs));  
  52.             }  
  53.         }else{  
  54.             log.error("请配置memcached服务地址!");  
  55.         }  
  56.           
  57.         //设置连接池大小,即客户端个数  
  58.         //xmemcached是基于nio的,通常不要设置连接池,一个连接可以支撑绝大多数应用。  
  59.         //除非你的应用并发规模特别大,比如我压测的时候测试100个线程或者300个线程并发的时候,连接池才能显示出优势。  
  60.         builder.setConnectionPoolSize(Integer.valueOf(prop.getProperty("connectionPoolSize")));  
  61.         //宕机报警  
  62.         builder.setFailureMode(Boolean.valueOf(prop.getProperty("failureMode")));  
  63.         //使用二进制协议,默认使用的TextCommandFactory即文本协议  
  64.         builder.setCommandFactory(new BinaryCommandFactory());  
  65.           
  66.         //1.Standard Hash, hash(key) mod server_count (余数分布)  
  67.         //默认使用余数分布  
  68.         //2.Consistent Hash(一致性哈希)  
  69.         //builder.setSessionLocator(new KetamaMemcachedSessionLocator());  
  70.         //3.Election Hash(选举散列)  
  71.         builder.setSessionLocator(new ElectionMemcachedSessionLocator());         
  72.         //SASL验证, 客户端授权验证授权验证,仅支持二进制协议  
  73.         builder.addAuthInfo(AddrUtil.getOneAddress("localhost:11213"), AuthInfo.typical("wy", "wy"));  
  74.     }  
  75.       
  76.     /** 
  77.      * 获取MemcachedClient 
  78.      *  
  79.      * @return 
  80.      */  
  81.     public static MemcachedClient getMemcachedClient(){  
  82.         try {  
  83.             if(memcacheddClient == null){  
  84.                 memcacheddClient = builder.build();  
  85.                 //当选择用URL当key的时候,MemcachedClient会自动将URL encode再存储。默认是关闭的  
  86.                 memcacheddClient.setSanitizeKeys(true);  
  87.                 //memcached存储大数据的效率是比较低的,当数据比较大的时候xmemcached会帮你压缩在存储,取出来的时候自动解压并反序列化,这个大小阀值默认是16K  
  88.                 memcacheddClient.getTranscoder().setCompressionThreshold(32768);  
  89.                 return memcacheddClient;  
  90.             }  
  91.         } catch (IOException e) {  
  92.             e.printStackTrace();  
  93.             log.error("获取MemcachedClient失败!");  
  94.         }  
  95.         return null;  
  96.     }  
  97.       
  98.     /** 
  99.      * 关闭MemcachedClient 
  100.      *  
  101.      * @param memcachedClient 
  102.      */  
  103.     public static void close(MemcachedClient memcachedClient){  
  104.         if(memcachedClient != null && !memcachedClient.isShutdown()){  
  105.             try {  
  106.                 memcachedClient.shutdown();  
  107.             } catch (IOException e) {  
  108.                 e.printStackTrace();  
  109.             }  
  110.         }  
  111.     }  
  112. }  

 XmemcachedTest.java

Java代码  
  1. package com.wy;  
  2.   
  3. import java.net.URL;  
  4. import java.util.concurrent.TimeoutException;  
  5.   
  6. import net.rubyeye.xmemcached.GetsResponse;  
  7. import net.rubyeye.xmemcached.KeyIterator;  
  8. import net.rubyeye.xmemcached.MemcachedClient;  
  9. import net.rubyeye.xmemcached.exception.MemcachedException;  
  10. import net.rubyeye.xmemcached.utils.AddrUtil;  
  11.   
  12. import org.junit.After;  
  13. import org.junit.Before;  
  14. import org.junit.Test;  
  15. import org.slf4j.Logger;  
  16. import org.slf4j.LoggerFactory;  
  17.   
  18. import com.wy.util.XmemcachedUtil;  
  19.   
  20. /** 
  21.  *  
  22.  *  
  23.  * @author wy 
  24.  * 
  25.  */  
  26. public class XmemcachedTest {  
  27.     private static Logger log = LoggerFactory.getLogger(XmemcachedTest.class);  
  28.     private MemcachedClient memcachedClient = null;  
  29.   
  30.     @Before  
  31.     public void setUp() throws Exception {  
  32.         long start1 = System.currentTimeMillis();  
  33.         memcachedClient = XmemcachedUtil.getMemcachedClient();  
  34.         long end1 = System.currentTimeMillis();  
  35.         System.out.println("创建MemcachedClient消耗时间:"+(end1 - start1));  
  36.     }  
  37.   
  38.     @After  
  39.     public void tearDown() throws Exception {  
  40.         XmemcachedUtil.close(memcachedClient);  
  41.     }  
  42.       
  43.     @Test  
  44.     public void main() {  
  45.         try {  
  46.             memcachedClient.flushAll();  
  47.             long start2 = System.currentTimeMillis();  
  48.             memcachedClient.set("wy", 3600, "wy test");  
  49.             long end2 = System.currentTimeMillis();  
  50.             System.out.println("向memcached中存值消耗时间:"+(end2 - start2));  
  51.               
  52.             long start3 = System.currentTimeMillis();  
  53.             System.out.println(memcachedClient.get("wy").toString());  
  54.             long end3 = System.currentTimeMillis();  
  55.             System.out.println("从memcached中取值消耗时间:"+(end3 - start3));  
  56.               
  57.             System.out.println(memcachedClient.add("wy123", 3600, "123") +" "+ memcachedClient.get("wy123").toString());  
  58.               
  59.             memcachedClient.append("wy", "_123");  
  60.             System.out.println(memcachedClient.get("wy").toString());  
  61.               
  62.             memcachedClient.replace("wy", 3600, "wy_123");  
  63.             System.out.println(memcachedClient.get("wy"));  
  64.               
  65.             /**  
  66.              * Memcached是通过cas协议实现原子更新,所谓原子更新就是compare and set,  
  67.              * 原理类似乐观锁,每次请求存储某个数据同时要附带一个cas值, memcached比对这个cas值与当前存储数据的cas值是否相等,  
  68.              * 如果相等就让新的数据覆盖老的数据,如果不相等就认为更新失败, 这在并发环境下特别有用  
  69.              */  
  70.             GetsResponse<Integer> result = memcachedClient.get("wy");  
  71.             long cas = result.getCas();  
  72.             //将wy的值修改为cas  
  73.             if(!memcachedClient.cas("wy", 3600, "cas", cas)){  
  74.                 System.err.println("cas error");  
  75.             }  
  76.               
  77.             memcachedClient.set("http://www.baidu.com", 3600, "http://www.baidu.com");  
  78.               
  79.             KeyIterator iterator = memcachedClient.getKeyIterator(AddrUtil.getOneAddress("127.0.0.1:11213"));  
  80.             while(iterator.hasNext()){  
  81.                  String key = iterator.next();  
  82.                  System.out.println("key = "+key);  
  83.             }  
  84.               
  85.             System.out.println("value = " + memcachedClient.get("wy"));  
  86.             System.out.println("value = " + memcachedClient.get("http://www.baidu.com"));  
  87.               
  88. //          memcachedClient.delete("wy");  
  89. //          System.out.println(memcachedClient.get("wy").toString());  
  90.               
  91.         } catch (TimeoutException e) {  
  92.             e.printStackTrace();  
  93.         } catch (InterruptedException e) {  
  94.             e.printStackTrace();  
  95.         } catch (MemcachedException e) {  
  96.             e.printStackTrace();  
  97.         }  
  98.     }  
  99.       
  100. }  

 

 

三、与Spring框架集成    

    applicationContext.xml

Xml代码  
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:p="http://www.springframework.org/schema/p"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
  6.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
  7.       
  8.     <context:property-placeholder location="memcached.properties" />  
  9.       
  10.     <bean id="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder"  
  11.         p:connectionPoolSize="${memcached.connectionPoolSize}" p:failureMode="${memcached.failureMode}">  
  12.         <!-- XMemcachedClientBuilder have two arguments.First is server list,and second is weights array. -->  
  13.         <constructor-arg>  
  14.             <list>  
  15.                 <bean class="java.net.InetSocketAddress">  
  16.                     <constructor-arg>  
  17.                         <value>${memcached.server1.host}</value>  
  18.                     </constructor-arg>  
  19.                     <constructor-arg>  
  20.                         <value>${memcached.server1.port}</value>  
  21.                     </constructor-arg>  
  22.                 </bean>  
  23.                 <bean class="java.net.InetSocketAddress">  
  24.                     <constructor-arg>  
  25.                         <value>${memcached.server2.host}</value>  
  26.                     </constructor-arg>  
  27.                     <constructor-arg>  
  28.                         <value>${memcached.server2.port}</value>  
  29.                     </constructor-arg>  
  30.                 </bean>  
  31.                 <bean class="java.net.InetSocketAddress">  
  32.                     <constructor-arg>  
  33.                         <value>${memcached.server3.host}</value>  
  34.                     </constructor-arg>  
  35.                     <constructor-arg>  
  36.                         <value>${memcached.server3.port}</value>  
  37.                     </constructor-arg>  
  38.                 </bean>  
  39.                 <bean class="java.net.InetSocketAddress">  
  40.                     <constructor-arg>  
  41.                         <value>${memcached.server4.host}</value>  
  42.                     </constructor-arg>  
  43.                     <constructor-arg>  
  44.                         <value>${memcached.server4.port}</value>  
  45.                     </constructor-arg>  
  46.                 </bean>  
  47.             </list>  
  48.         </constructor-arg>  
  49.         <!-- server's weights -->  
  50.         <constructor-arg>  
  51.             <list>  
  52.                 <value>${memcached.server1.weight}</value>  
  53.                 <value>${memcached.server2.weight}</value>  
  54.                 <value>${memcached.server3.weight}</value>  
  55.                 <value>${memcached.server4.weight}</value>  
  56.             </list>  
  57.         </constructor-arg>  
  58.         <!-- 协议 -->  
  59.         <property name="commandFactory">  
  60.             <bean class="net.rubyeye.xmemcached.command.TextCommandFactory" />  
  61.         </property>  
  62.         <!-- 分布策略  -->  
  63.         <property name="sessionLocator">  
  64.             <bean class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator" />  
  65.         </property>  
  66.         <!-- 序列化转换器  -->  
  67.         <property name="transcoder">  
  68.             <bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />  
  69.         </property>  
  70.     </bean>  
  71.     <!-- Use factory bean to build memcached client -->  
  72.     <bean id="memcachedClient" factory-bean="memcachedClientBuilder"  
  73.         factory-method="build" destroy-method="shutdown" />  
  74.           
  75. </beans>  

 MemcachedSpringTest.java

Java代码  
  1. package com.wy;  
  2.   
  3. import static junit.framework.Assert.*;  
  4.   
  5. import java.util.concurrent.TimeoutException;  
  6.   
  7. import net.rubyeye.xmemcached.MemcachedClient;  
  8. import net.rubyeye.xmemcached.exception.MemcachedException;  
  9.   
  10. import org.junit.Before;  
  11. import org.junit.Test;  
  12. import org.springframework.context.ApplicationContext;  
  13. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  14.   
  15. public class MemcachedSpringTest {  
  16.   
  17.     private ApplicationContext app;  
  18.     private MemcachedClient memcachedClient;  
  19.   
  20.     @Before  
  21.     public void init() {  
  22.         app = new ClassPathXmlApplicationContext("applicationContext.xml");  
  23.         memcachedClient = (MemcachedClient) app.getBean("memcachedClient");  
  24.     }  
  25.   
  26.     @Test  
  27.     public void test() {  
  28.         try {  
  29.             // 设置/获取  
  30.             memcachedClient.set("wy", 36000, "set/get");  
  31.             assertEquals("set/get", memcachedClient.get("wy"));  
  32.   
  33.             // 替换  
  34.             memcachedClient.replace("wy", 36000, "replace");  
  35.             assertEquals("replace", memcachedClient.get("wy"));  
  36.   
  37.             // 移除  
  38.             memcachedClient.delete("wy");  
  39.             assertNull(memcachedClient.get("wy"));  
  40.               
  41.         } catch (TimeoutException e) {  
  42.             e.printStackTrace();  
  43.         } catch (InterruptedException e) {  
  44.             e.printStackTrace();  
  45.         } catch (MemcachedException e) {  
  46.             e.printStackTrace();  
  47.         }  
  48.     }  
  49. }  

 

 

四、SASL验证

   

 参考http://lguan.iteye.com/blog/1279537

 

 

 

 

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Memcached笔记
安装memcached的小事
simple
spring调用memcached client
用xmemcache作为JPA(Hibernate实现)二级缓存
XMemcached与Spring3.2缓存框架集成
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服