Xmemcached简单使用

引用自这里

一、XMemcached是什么?

经常碰到的一个问题是很多朋友对 memcached 不了解,误以为 xmemcached 本身是一个缓存系统。Memcached是一个开源的,C写的分布式key-value缓存,XMemcached只是它的一个访问客户端。Memcached通过网络协议跟客户端交互,通过客户端你才可以去使用memcached,xmemcached是它的java客户端之一。

二、为什么要选择xmemcached?

memcached的java客户端有多个选择,为什么要选择xmemcached?理由如下:

1、支持所有的文本协议和二进制协议,支持连接 Kestrel TokyoTyrant 等memcached协议兼容的系统并作特殊处理。
2、支持动态添加和删除memcached节点。
3、支持客户端统计
4、支持JMX监控和统计,可以通过JMX增删节点。
5、高性能
6、支持节点的权重设置
7、支持nio的连接池,在高负载环境下提高吞吐量。

三、对jdk版本有什么要求?

Xmemcached仅支持jdk1.5及以上版本。

四、使用的时候需要创建多个MemcachedClient对象吗?MemcachedClient是不是线程安全?

MemcachedClient是线程安全的,由于xmemcached的网络层实现是基于nio长连接的,因此你并不需要重复创建多个MemcachedClient对象,通常来说将MemcachedClient设置为全局的唯一单例的服务使用,如果是使用spring配置,那更是简单,在spring配置文件里配置一个MemcachedClient,其他对象引用即可使用。

五、为什么会抛出java.util.TimeoutException?

这是由于xmemcached的通讯层是基于非阻塞IO的,那么在请求发送给memcached之后,需要等待应答的到来,这个等待时间默认是1秒,如果超过1秒就抛出java.util.TimeoutExpcetion给用户。如果你频繁抛出此异常,可以尝试将全局的等待时间设置长一些,如我在压测中设置为5秒:
MemcachedClient  memcachedClient=……
memcachedClient.setOpTimeout(5000L);

请注意,setOpTimeout设置的是全局的等待时间,如果你仅仅是希望将get或者set等操作的超时延长一点,那么可以通过这些方法的重载方法来使用:
<T> T get(java.lang.String key, long timeout)

boolean set(java.lang.String key,  int exp,java.lang.Object value,
             long timeout)

……


六、Kestrel和TokyoTyrant不支持flag字段,xmemcached是怎么解决的?

Xmemcached在存储的value前面自动加上和去除4个字节的flag,这一切对应用来说是透明的。具体请看用户指南。


七、连接memcacheq,取出来的消息比放进去的多?


这是由于memcacheq和kestrel一样,不支持multi get协议,因此只要关闭xmemcached的multi get优化就可以了。

memcachedClient.setOptimizeGet( false);

所谓multi get优化是指xmemcached会将连续的单个get请求合并成一个multi get请求作批量获取,提高效率。

八、连接kestrel,为什么过一段时间会自动断开并重连?

你可能使用的是kestrel 1.2以下版本,kestrel 1.2才支持version协议,xmemcached是基于version协议做心跳检测,因此当使用kestrel 1.2以下版本的时候会发生心跳检测失败并断开连接重连的情况,你可以升级kestrel,也可以关闭心跳检测:

memcachedClient.setEnableHeartBeat( false);

九、我使用maven,怎么引用xmemcached?

xmemcached 1.2.5已经加入了maven的中心仓库,因此你可以直接引用
   < dependency >
       < groupId >com.googlecode.xmemcached </ groupId >
       < artifactId >xmemcached </ artifactId >
       < version >1.2.5 </ version >
  </ dependency >

如果是之前版本,我推荐你升级,或者自己手工加入私人的maven仓库。

十、连接池是怎么回事?设置多大为好?

在高负载环境下,nio的单连接也会遇到瓶颈,此时你可以通过设置连接池来让更多的连接分担memcached的请求负载,从而提高系统的吞吐量。设置连接池通过
MemcachedClientBuilder builder =  new    XMemcachedClientBuilder(AddrUtil.getAddresses("localhost:12000"));

builder.setConnectionPoolSize(5);
MemcachedClient client=builder.build();

或者通过spring配置也可以。

连接池通常不建议设置太大,我推荐在0-30之间为好,太大则浪费系统资源,太小无法达到分担负载的目的。

十一、性能建议及优化手段

    性能的调整只能给出一般性的原则,实际情况千差万别,每次调整都需要做实际的测量才能确定是否带来期望的效果。

1、如果你的数据较小,如在1K以下,默认的配置选项已经足够。如果你的数据较大,我会推荐你调整网络层的TCP选项,如设置socket的接收和发送缓冲区更大,启用Nagle算法等等:    
            MemcachedClientBuilder builder =  new XMemcachedClientBuilder(
                    AddrUtil.getAddresses(servers));
            builder.setSocketOption(StandardSocketOption.SO_RCVBUF, 32 * 1024);  //  设置接收缓存区为32K,默认16K
            builder.setSocketOption(StandardSocketOption.SO_SNDBUF, 16 * 1024);  //  设置发送缓冲区为16K,默认为8K
            builder.setSocketOption(StandardSocketOption.TCP_NODELAY,  false);  //  启用nagle算法,提高吞吐量,默认关闭

默认如果连接超过5秒没有任何IO操作发生即认为空闲并发起心跳检测,你可以调长这个时间:  
  builder.getConfiguration().setSessionIdleTimeout(10000);   //  设置为10秒;

更多网络层配置选项请参见Configuration类。

2、Xmemcached默认会做两个优化:将连续的单个get合并成一个multi get批量操作获取,将连续的请求合并成socket发送缓冲区大小的buffer发送。
如果你对响应时间比较在意 ,那么可以将合并的因子减小,或者关闭合并buffer的优化:
    memcachedClient.setMergeFactor(50);    // 默认是150,缩小到50
    memcachedClient.setOptimizeMergeBuffer( false);   // 关闭合并buffer的优化

如果你对吞吐量更在意 ,那么也可将合并因子调大,默认是150。但是也不可太大,太大可能导致平均响应时间延长。

3、如果你对心跳检测不在意,也可以关闭心跳检测,减小系统开销
memcachedClient.setEnableHeartBeat( false);
这个关闭,仅仅是关闭了心跳的功能,客户端仍然会去统计连接是否空闲,禁止统计可以通过:
builder.getConfiguration().setStatisticsServer( false);


简单的使用

package xmemcache;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.command.BinaryCommandFactory;
import net.rubyeye.xmemcached.exception.MemcachedException;
import net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator;
import net.rubyeye.xmemcached.transcoders.SerializingTranscoder;
import net.rubyeye.xmemcached.utils.AddrUtil;

public class MemcachedClientTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MemcachedClientBuilder builder = new XMemcachedClientBuilder(
				AddrUtil.getAddresses("127.0.0.1:11211"), new int[] {1});
		
		builder.setConnectionPoolSize(50);							//最多连接数
		
		//使用二进制文件
		builder.setCommandFactory(new BinaryCommandFactory());		//在1.4之前使用会报timeout错误,1.4之后可用
		
		//使用一致性hash
		builder.setSessionLocator(new KetamaMemcachedSessionLocator()); 
		
		//使用序列化传输编码
		builder.setTranscoder(new SerializingTranscoder());
		
		//使用压缩
		builder.getTranscoder().setCompressionThreshold(1); 		//设置压缩阈值,单位为字节
		
		MemcachedClient memcachedClient = null;
		
		try {
			memcachedClient = builder.build();
			memcachedClient.setOpTimeout(50000L);					//超时时间
			memcachedClient.setEnableHeartBeat(false);				//心跳检测
			
			
			
			try {
				memcachedClient.set("key", 36000, "value");
				
				String value = (String)memcachedClient.get("key");
				if(null!=value){
					System.out.println("value 值为: "+value);
				}
				else{
					System.out.println("key = key对应的value值不存在!");
				}
				
				
				System.out.println(memcachedClient.delete("key"));
				
				value = (String)memcachedClient.get("key");
				System.out.println(value);
				
			} catch (TimeoutException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (MemcachedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally{
			if(null != memcachedClient){
				try {
					memcachedClient.shutdown();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

}



timeout问题,在1.4版本之前如果在设置client的时候加入了builder.setCommandFactory(new BinaryCommandFactory()) 使用二进制文件,则会报错,

在1.4版本之后添加无问题注意版本选择

你可能感兴趣的:(memcached)