`

XMemcached使用指南【一】

 
阅读更多

XMemcached的Wiki: http://code.google.com/p/xmemcached/wiki/User_Guide_zh

 

XMemcached简介

XMemcached是一个新java memcached client。也许你还不知道memcached是什么?可以先看看这里。简单来说,Memcached 是一个高性能的分布式内存对象的key-value缓存系统,用于动态Web应用以减轻数据库负载,现在也有很多人将它作为内存式数据库在使用,memcached通过它的自定义协议与客户端交互,而XMemcached就是它的一个java客户端实现。

Memcached的java客户端已经存在两个了:官方提供的基于传统阻塞io由Greg Whalin维护的客户端、Dustin Sallings实现的基于java nio的Spymemcached。另外还有一些在此基础上的改进版本。相比于这些客户端,XMemcached有什么优点呢?或者说,它的主要特性有哪些?

XMemcached的主要特性

高性能

XMemcached同样是基于java nio的客户端,java nio相比于传统阻塞io模型来说,有效率高(特别在高并发下)和资源耗费相对较少的优点。传统阻塞IO为了提高效率,需要创建一定数量的连接形成连接池,而nio仅需要一个连接即可(当然,nio也是可以做池化处理),相对来说减少了线程创建和切换的开销,这一点在高并发下特别明显。因此XMemcached与Spymemcached在性能都非常优秀,在某些方面(存储的数据比较小的情况下)Xmemcached比Spymemcached的表现更为优秀,具体可以看这个Java Memcached Clients Benchmark

支持完整的协议

Xmemcached支持所有的memcached协议,包括1.4.0正式开始使用的二进制协议

支持客户端分布

Memcached的分布只能通过客户端来实现,XMemcached实现了此功能,并且提供了一致性哈希(consistent hash)算法的实现。

允许设置节点权重

XMemcached允许通过设置节点的权重来调节memcached的负载,设置的权重越高,该memcached节点存储的数据将越多,所承受的负载越大。

动态增删节点

XMemcached允许通过JMX或者代码编程实现节点的动态添加或者移除,方便用户扩展和替换节点等。

支持JMX

XMemcached通过JMX暴露的一些接口,支持client本身的监控和调整,允许动态设置调优参数、查看统计数据、动态增删节点等。

与Spring框架和Hibernate-memcached的集成

鉴于很多项目已经使用Spring作为IOC容器,因此XMemcached也提供了对Spring框架的集成支持。Hibernate-memcached是一个允许将memcached作为hibernate的二级缓存的开源项目,默认是使用Spymemcached,Xmemcached提供了对这个项目的支持,允许替换Spymemcached.

客户端连接池

刚才已经提到java nio通常对一个memcached节点使用一个连接,而XMemcached同样提供了设置连接池的功能,对同一个memcached可以创建N个连接组成连接池来提高客户端在高并发环境下的表现,而这一切对使用者来说却是透明的。启用连接池的前提条件是保证数据之间的独立性或者数据更新的同步,对同一个节点的各个连接之间是没有做更新同步的,因此应用需要保证数据之间是相互独立的或者全部采用CAS更新来保证原子性。

可扩展性

XMemcached是基于java nio框架yanf4j实现的,因此在实现上结构相对清楚,分层比较明晰,在xmemcached 1.2.5之后已经将yanf4j合并到xmemcached,因此不再需要依赖yanf4j,下面是XMemcached的主要类的UML图:

使用指南

在简单介绍完XMemcached的主要特性之后,我们将进入XMemcached的使用环节,这里将按照从简单到复杂的顺序讲解一些例子,以方便用户深入了解XMemcached的使用。

依赖包

Xmemcached依赖slf4j

在测试下面讲到的代码之前,请先自行下载依赖包或者下载包含了依赖包的xmemcached。

如果你使用maven

如果你使用maven构建你的项目,那么只要添加dependency即可使用xmemcached(仅对1.2.5及以后版本有效)

 <dependency>
       <groupId>com.googlecode.xmemcached</groupId>
       <artifactId>xmemcached</artifactId>
       <version>{版本号}</version>
  </dependency>

简单例子

对于用户来说,最主要的功能是存取数据,假设我们有一个memcached节点IP地址或者域名是host,端口是11211,一个简单的存取数据的例子如下:

    MemcachedClientBuilder builder =newXMemcachedClientBuilder(
                                        AddrUtil.getAddresses("localhost:11211"));
    MemcachedClient memcachedClient = builder.build();
    try{
                memcachedClient.set("hello",0,"Hello,xmemcached");
                String value = memcachedClient.get("hello");
                System.out.println("hello="+ value);
                memcachedClient.delete("hello");
                value = memcachedClient.get("hello");
                System.out.println("hello="+ value);
    }catch(MemcachedException e){
                System.err.println("MemcachedClient operation fail");
                e.printStackTrace();
    }catch(TimeoutException e){
                System.err.println("MemcachedClient operation timeout");
                e.printStackTrace();
    }catch(InterruptedException e){
                // ignore
    }
    try{
              //close memcached client
                memcachedClient.shutdown();
    }catch(IOException e){
                System.err.println("Shutdown MemcachedClient fail");
                e.printStackTrace();
    }

为了节省篇幅,本文的所有代码示例都没有给出完整的package名,具体包名请查询javadoc或者使用IDE工具帮助引入。

因为XMemcachedClient的创建有比较多的可选项,因此提供了一个XMemcachedClientBuilder类用于构建MemcachedClient。MemcachedClient是主要接口,操作memcached的主要方法都在这个接口,XMemcachedClient是它的一个实现。传入的memcached节点列表要求是类似"host1:port1 host2:port2 …"这样的字符串,通过AddrUtil.getAddresses方法获取实际的IP地址列表。

存储数据是通过set方法,它有三个参数,第一个是存储的key名称,第二个是expire时间(单位秒),超过这个时间,memcached将这个数据替换出去,0表示永久存储(默认是一个月),第三个参数就是实际存储的数据,可以是任意的java可序列化类型。获取存储的数据是通过get方法,传入key名称即可。如果要删除存储的数据,这是通过delete方法,它也是接受key名称作为参数。XMemcached由于是基于nio,因此通讯过程本身是异步的,client发送一个请求给memcached,你是无法确定memcached什么时候返回这个应答,客户端此时只有等待,因此还有个等待超时的概念在这里。客户端在发送请求后,开始等待应答,如果超过一定时间就认为操作失败,这个等待时间默认是5秒(1.3.8开始改为5秒,之前是1秒),上面例子展现的3个方法调用的都是默认的超时时间,这三个方法同样有允许传入超时时间的重载方法,例如

   value=client.get(“hello”,3000);

就是等待3秒超时,如果3秒超时就跑出TimeutException,用户需要自己处理这个异常。因为等待是通过调用CountDownLatch.await(timeout)方法,因此用户还需要处理中断异常InterruptException。最后的MemcachedException表示Xmemcached内部发生的异常,如解码编码错误、网络断开等等异常情况。

touch更新数据超时时间

经常有这样的需求,就是希望更新缓存数据的超时时间(expire time),在没有touch协议之前,你需要整体的get-set一次:

    value=client.get("a");
    client.set("a",new-expire-time,value);

两次操作,加上value的序列化/反序列化、网络传输,这个开销可不小。幸好,现在memcached已经支持touch协议,只需要传递key就更新缓存的超时时间:

    client.touch(key,new-expire-time);

xmemcached 1.3.6开始支持二进制协议的touch命令,1.3.8开始支持文本协议的touch命令。

有时候你希望获取缓存数据并更新超时时间,这时候可以用getAndTouch方法(仅二进制协议支持):

   client.getAndTouch(key,new-expire-time);

客户端分布

Memcached的分布是通过客户端实现的,客户端根据key的哈希值得到将要存储的memcached节点,并将对应的value存储到相应的节点。

XMemcached同样支持客户端的分布策略,默认分布的策略是按照key的哈希值模以连接数得到的余数,对应的连接就是将要存储的节点。如果使用默认的分布策略,你不需要做任何配置或者编程。

XMemcached同样支持一致性哈希(consistent hash),通过编程设置:

        MemcachedClientBuilder builder =newXMemcachedClientBuilder(AddrUtil
                                .getAddresses(properties.getProperty("test.memcached.servers"))
        builder.setSessionLocator(newKetamaMemcachedSessionLocator());
        MemcachedClient client=builder.build();

配置的方式请见spring配置一节。

XMemcached还提供了额外的一种哈希算法——选举散列,在某些场景下可以替代一致性哈希

  MemcachedClientBuilder builder =newXMemcachedClientBuilder(
                                        AddrUtil.getAddresses("server1:11211 server2:11211 server3:11211"));
  builder.setSessionLocator(newElectionMemcachedSessionLocator());
  MemcachedClient mc = builder.build();

CAS操作

Memcached是通过cas协议实现原子更新,所谓原子更新就是compare and set,原理类似乐观锁,每次请求存储某个数据同时要附带一个cas值,memcached比对这个cas值与当前存储数据的cas值是否相等,如果相等就让新的数据覆盖老的数据,如果不相等就认为更新失败,这在并发环境下特别有用。XMemcached提供了对CAS协议的支持(无论是文本协议还是二进制协议),CAS协议其实是分为两个步骤:获取CAS值和尝试更新,因此一个典型的使用场景如下:

  GetsResponse<Integer> result = client.gets("a");
  long cas = result.getCas(); 
  //尝试将a的值更新为2
  if(!client.cas("a",0,2, cas)){
        System.err.println("cas error");
   }

首先通过gets方法获取一个GetsResponse,此对象包装了存储的数据和cas值,然后通过cas方法尝试原子更新,如果失败打印”cas error”。显然,这样的方式很繁琐,并且如果你想尝试多少次原子更新就需要一个循环来包装这一段代码,因此XMemcached提供了一个*CASOperation*接口包装了这部分操作,允许你尝试N次去原子更新某个key存储的数据,无需显式地调用gets获取cas值,上面的代码简化为:

 client.cas("a",0,newCASOperation<Integer>(){
                        publicint getMaxTries(){
                                return1;
                        }

                        publicInteger getNewValue(long currentCAS,Integer currentValue){
                                        return2;
                        }
        });

CASOpertion接口只有两个方法,一个是设置最大尝试次数的getMaxTries方法,这里是尝试一次,如果尝试超过这个次数没有更新成功将抛出一个TimeoutException,如果你想无限尝试(理论上),可以将返回值设定为Integer.MAX_VALUE;另一个方法是根据当前获得的GetsResponse来决定更新数据的getNewValue方法,如果更新成功,这个方法返回的值将存储成功,这个方法的两个参数是最新一次gets返回的GetsResponse结果。

更全面的例子

一些更全面的例子,展现了MemcachedClient接口的主要方法:

  MemcachedClientBuilder builder =newXMemcachedClientBuilder(
                                        AddrUtil.getAddresses(“localhost:12000”));
  MemcachedClient client = builder.build();
                        client.flushAll();
  if(!client.set("hello",0,"world")){
                System.err.println("set error");
  }
  if(client.add("hello",0,"dennis")){
                System.err.println("Add error,key is existed");
  }
  if(!client.replace("hello",0,"dennis")){
                System.err.println("replace error");
  }
  client.append("hello"," good");
  client.prepend("hello","hello ");
  String name = client.get("hello",newStringTranscoder());
  System.out.println(name);
  client.deleteWithNoReply(“hello”);

首先存储了hello对应的world字符串,然后调用add和replace方法去尝试添加和替换,因为数据已经存在,因此add会失败,同样replace在数据存在的情况才会成功,也就是将hello对应的数据更新为dennis,然后通过append和prepend方法在dennis前后加上了字符串hello和good,因此通过get返回的结果是hello dennis good。而删除数据则是通过deleteWithNoReply方法,这个方法删除数据并且告诉memcached不用返回应答,因此这个方法不会等待应答直接返回,特别适合于批量处理;同样地,set、add、replace等方法也有相应的ithNoReply重载版本,具体请看API文档。

迭代所有key

Memcached本身并没有提供迭代所有key的方法,但是通过"stats items"和"stats cachedump"统计协议可以做到迭代所有的key,这个迭代过程是低效,因此如无必要,并不推荐使用此方法。XMemcached仅提供了文本协议的迭代支持,其他协议暂未支持。

想迭代所有的key,你只需要获取一个KeyIterator即可:

MemcachedClient client=...KeyIterator it=client.getKeyIterator(AddrUtil.getOneAddress("localhost:11211"));while(it.hasNext()){
   String key=it.next();}

Incr/Decr

下面这个例子展现了incr/decr操作的使用,两个操作类似Java中的原子类如AtomicIntger,用于原子递增或者递减变量数值:

 assert(1==this.memcachedClient.incr("a",5,1));
 assert(6==this.memcachedClient.incr("a",5));
 assert(10==this.memcachedClient.incr("a",4));
 assert(9==this.memcachedClient.decr("a",1));
 assert(7==this.memcachedClient.deccr("a",2));

incr和decr都有三个参数的方法,第一个参数指定递增的key名称,第二个参数指定递增的幅度大小,第三个参数指定当key不存在的情况下的初始值。两个参数的重载方法省略了第三个参数,默认指定为0。

Xmemcached还提供了一个称为计数器的封装,它封装了incr/decr方法,使用它就可以类似AtomicLong那样去操作计数:

  Counter counter=client.getCounter("counter",0);
  counter.incrementAndGet();
  counter.decrementAndGet();
  counter.addAndGet(-10);

其中getCounter的第二个参数是计数器的初始值。

命名空间

从1.4.2开始,xmemcached提供了memcached命名空间的封装使用,你可以将一组缓存项放到同一个命名空间下,可以让整个命名空间下所有的缓存项同时失效,例子:

String ns ="namespace";this.memcachedClient.withNamespace(ns,
                                newMemcachedClientCallable<Void>(){

                                        publicVoid call(MemcachedClient client)
                                                        throwsMemcachedException,InterruptedException,
                                                        TimeoutException{
                                                 //a,b,c都在namespace下
                                                client.set("a",1);
                                                client.set("b",1);
                                                client.set("c",1);
                                                returnnull;
                                        }
                                });//获取命名空间内的a对应的值Integer aValue =this.memcachedClient.withNamespace(ns,
                                newMemcachedClientCallable<Integer>(){

                                        publicInteger call(MemcachedClient client)
                                                        throwsMemcachedException,InterruptedException,
                                                        TimeoutException{
                                                  return client.get("a");
                                        }
                                });//使得命名空间失效this.memcachedClient.invalidateNamespace(ns);

查看统计信息

Memcached提供了统计协议用于查看统计信息:

   Map<InetSocketAddress,Map<String,String>> result=client.getStats();

getStats方法返回一个map,其中存储了所有已经连接并且有效的memcached节点返回的统计信息,你也可以统计具体的项目,如统计items项目:

   Map<InetSocketAddress,Map<String,String>> result=client.getStatsByItem("items");

只要向getStatsByItem传入需要统计的项目名称即可。

SASL验证

Memcached 1.4.3开始支持SASL验证客户端,在服务器配置启用SASL之后,客户端需要通过授权验证才可以跟memcached继续交互,否则将被拒绝请求。XMemcached 1.2.5开始支持这个特性。假设memcached设置了SASL验证,典型地使用CRAM-MD5或者PLAIN的文本用户名和密码的验证机制,假设用户名为cacheuser,密码为123456,那么编程的方式如下:

        MemcachedClientBuilder builder =newXMemcachedClientBuilder(
                                        AddrUtil.getAddresses("localhost:11211"));
        builder.addAuthInfo(AddrUtil.getOneAddress("localhost:11211"),AuthInfo
                                        .typical("cacheuser","123456"));
        // Must use binary protocol
        builder.setCommandFactory(newBinaryCommandFactory());
        MemcachedClient client=builder.build();

请注意,授权验证仅支持二进制协议。

 

 

分享到:
评论

相关推荐

    Xmemcached用户指南

    为了帮助读者更好地理解XMemcached的基本使用方法,下面提供了一个简单的示例代码: ```java // 创建Memcached客户端 MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(...

    Xmemcached用户指南.docx

    开始使用XMemcached,首先需要创建一个`XMemcachedClientBuilder`实例,并指定Memcached服务器的地址。例如,若服务器IP为`localhost`,端口为`11211`,代码如下: ```java MemcachedClientBuilder builder = new ...

    Xmemcached用户指南.pdf

    【Xmemcached用户指南】 XMemcached是一款专为Java设计的高效、全面的Memcached客户端。Memcached是一款高性能的分布式内存对象缓存系统,常用于缓解数据库负载,它通过简单的key-value存储方式来缓存数据。...

    Xmemcached用户指南 后端 - Java.zip

    本文档将深入探讨如何使用Xmemcached进行后端开发,帮助Java开发者更好地理解和利用这一强大的工具。 1. **Xmemcached简介** Xmemcached是基于原生Memcached协议实现的Java客户端,提供了异步非阻塞I/O,具有低...

    Xmemcached官方中文手册

    阅读这份指南,开发者能够全面掌握Xmemcached的使用技巧和最佳实践。 总的来说,这份**Xmemcached官方中文手册** 是学习和使用Xmemcached不可或缺的参考资料,无论你是初学者还是有经验的开发者,都能从中受益匪浅...

    xmemcached 中文开发手册

    以下是一段简单的XMemcached使用示例,展示如何建立连接、读写数据以及释放资源: ```java import com.google.code.yanf4j.core.Session; import com.google.code.yanf4j.util.IOUtils; import ...

    java memcache使用例子

    Java Memcached 使用指南 Memcached 是一款高性能、分布式内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库的负载,提升数据访问速度。在Java环境中,我们可以使用各种客户端库来与Memcached进行交互。本篇...

    memcached安装及java应用使用memcached

    **标题解析:** “memcached安装及java应用使用...总结,本文应该涵盖了从安装memcached到在Java应用中使用它的全面指南,包括相关配置、操作、最佳实践和优化技巧,旨在帮助开发者充分利用memcached来提升应用性能。

    memcached 的使用,以及jar包,和工具

    2. **Java客户端库**:了解如何使用Java(如XMemcached或spymemcached)与memcached交互,包括设置、获取、删除键值对等操作。 3. **管理工具**:掌握`MemCachedManager.java`类可能提供的功能,如连接、操作和监控...

    阿里软件java版memcached安装文件和demo项目

    2. **Java客户端**:在Java环境中,通常使用如spymemcached、xmemcached等客户端库来与Memcached服务器通信。此处提到的阿里封装的jar,可能是对这些客户端的定制化实现或优化,可能包含更适应阿里巴巴业务场景的...

    memcached相关资料及spring配置文件和封装接口和类

    在本压缩包中,你应该能找到这个安装文件,确保按照官方指南正确安装和配置。 对于 **Java** 开发者,使用 Memcached 需要引入特定的 **Jar 包**。这些 Jar 包通常包含 Java 客户端库,如 `spymemcached` 或 `...

    tomcat 8 memcached 相关软件包

    首先,你需要在你的项目中添加一个支持Memcached的Java客户端库,如spymemcached或者xmemcached。这些库提供与Memcached服务器通信的接口,允许你在代码中存取session数据。 然后,在Tomcat的server.xml配置文件中...

    tomcat+memcached共享session所需jar包

    Tomcat是Apache软件基金会的Jakarta项目下的一个开源Java Servlet容器,而Memcached则是一种广泛使用的分布式内存对象缓存系统,常用于缓解数据库负载,提高网站性能。当在分布式环境中运行多个Tomcat服务器时,确保...

    memcache学习资料(包含memcache和java_memcache相应的jar)

    `java_memcache`相关的JAR文件通常包含了Java Memcached客户端库,如Xmemcached或spymemcached,这些库提供了API,让Java开发者能够方便地在Java应用中集成和使用Memcached服务。 在Windows环境下部署和使用...

    tomcat与memcached集群jar

    此外,“里面还有一份文档”可能提供关于如何设置和使用这些JAR文件的指南或步骤,这对于初学者来说非常有用。 关于“标签”,我们看到有三个关键术语: 1. **Tomcat**:正如之前所述,这是一个广泛使用的Java应用...

    nodeJS学习的课程作业

    - **Java 客户端**:介绍常用的 Java Memcached 客户端库,如 Spymemcached 和 Xmemcached。 - **代码示例**:提供 Java 代码示例,演示如何使用这些客户端库与 Memcached 服务器进行交互。 以上是对“nodeJS学习的...

    memcached tomcat 共享session

    这些库如spymemcached或xmemcached,可以从Maven仓库获取,或者从提供的压缩包文件中(如libgcc_s_sjlj-1.dll、pthreadGC2.dll、mingwm10.dll)找到对应的库文件。 3. **配置Tomcat**:修改Tomcat的`context.xml`或...

    Memcache资料合集

    2. "Memcached Study.pdf":可能包含更全面的Memcached学习指南,包括基本概念、使用方法、优化策略等。 3. "memcached入门到理解.pdf":适合初学者,从基础开始介绍,逐步深入理解Memcached。 4. "Java_Memcache....

    memcached简单实用

    4. **Java接口**:对于Java开发者,与memcached交互通常需要使用特定的Java客户端库,如spymemcached或xmemcached。这些库提供了简单的API,允许开发者将Java对象序列化为字节,然后存储和检索到memcached中。提供的...

    spring调用memcached client for java

    `readme.txt`可能包含关于如何配置和使用这个集成的详细指南,而`src`目录则包含了示例代码或者项目的源码。 通过以上步骤,你可以将Memcached有效地集成到Spring应用中,利用其高速缓存能力提升应用性能。注意,...

Global site tag (gtag.js) - Google Analytics