XMemcached使用--好文转载

2024-06-08 01:18

本文主要是介绍XMemcached使用--好文转载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自:http://blog.csdn.net/ljhabc1982/article/details/6338898

 

Xmemcached

一、 XMemcached 简介

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

二、 使用指南

2.1 简单例子

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

 

MemcachedClientBuilder builder = new XMemcachedClientBuilder(

               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 {

           memcachedClient.shutdown();

       } catch (IOException e) {

           System. err .println( "Shutdown MemcachedClient fail" );

           e.printStackTrace();

       }

 

因为 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 什么时候返回这个应答,客户端此时只有等待,因此还有个等待超时的概念在这里。客户端在发送请求后,开始等待应答,如果超过一定时间就认为操作失败,这个等待时间默认是一秒,上面例子展现的 3 个方法调用的都是默认的超时时间,这三个方法同样有允许传入超时时间的重载方法,例如

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

 

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

 

2.2 CAS 操作

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

GetsResponse<Integer> result = client.gets( "a" );

long cas = result.getCas();

if (!client.cas( "a" , 0, 2, cas)) {

       System. err .println( "cas error" );

}

 

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

client.cas( "a" , 0, new CASOperation<Integer>() {

 

              public int getMaxTries() {

                  return 1;

              }

 

              public Integer getNewValue( long currentCAS, Integer currentValue) {

                  return 2;

              }

           });

 

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

 

2.3 更全面的例子

 

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

MemcachedClientBuilder builder = new XMemcachedClientBuilder(

                  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" new StringTranscoder());

           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 等方法也有相应的 withNoReply 重载版本,具体请看 API 文档。

 

下面这个例子展现了 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 

 

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

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

 

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

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

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

 

MemcachedClientBuilder builder = new XmemcachedClientBuilder

(AddrUtil.getAddresses("10.180.44.224:11211 zhouxq:11211"),new int[]{1,3});

 

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

xmemcached 的权重是通过复制连接的多个引用来实现的,比如权重为 3 ,那么就复制 3 个同一个连接的引用放在集合中让 MemcachedSessionLocator 查找。

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

  public void setServerWeight(String server, int weight);

weight  servers 对应的节点的权重

weight 可以有也可无

weight 值大则权重大,否则小

 

传入一个 int 数组,里面的元素就是节点对应的权重值,比如这里设置 "10.180.44.224:1121" 节点的权重为 1 ,而 "zhouxq:11211" 的权重为 3 

类似的 XMemcachedClient()  XMemcachedClientBuilder 相同

 

设置连接池大小

     builder.setConnectionPoolSize(5);

 

 Spring 框架集成

通过 XMemcachedClientFactoryBean 类,即可与 spring 框架集成

 

最简单例子

<bean name="memcachedClient" destroy-method="shutdown"

class="net.rubyeye.xmemcached.utils.XMemcachedClientFactoryBean">

<property name="servers">

<value>host1:port1 host2:port2</value>

</property>

</bean>

然后在 bean 中就可以使用 memcachedClient 

 

复杂一点儿的例子

<bean name="memcachedClient" destroy-method="shutdown"

                class="net.rubyeye.xmemcached.utils.XMemcachedClientFactoryBean">

<property name="servers">

<value>host1:port1 host2:port2 host3:port3</value>

</property>

<property name="weights">

<list>

                  <value>1</value>

<value>2</value>

<value>3</value>

</list>

</property>

<property name="sessionLocator">

<bean class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator"/>

</property>

<property name="transcoder">

<bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />

</property>

<property name="bufferAllocator">

       <bean class="net.rubyeye.xmemcached.buffer.SimpleBufferAllocator">

</property>

</bean>

 

其中各参数的意义:

参数

含义

servers

服务器列表,格式: ip:port

weights

主机映射: host1 对应 1 号、 host2 对应 2  ..

sessionLocator

Session 分配器,有自带的,影响分布式

transcoder

通信编码方式

bufferAllocator

缓冲区分配器

 

 转自:http://blog.csdn.net/ljhabc1982/article/details/6338898

这篇关于XMemcached使用--好文转载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1040844

相关文章

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB

Maven的使用和配置国内源的保姆级教程

《Maven的使用和配置国内源的保姆级教程》Maven是⼀个项目管理工具,基于POM(ProjectObjectModel,项目对象模型)的概念,Maven可以通过一小段描述信息来管理项目的构建,报告... 目录1. 什么是Maven?2.创建⼀个Maven项目3.Maven 核心功能4.使用Maven H

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

SpringBoot使用GZIP压缩反回数据问题

《SpringBoot使用GZIP压缩反回数据问题》:本文主要介绍SpringBoot使用GZIP压缩反回数据问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot使用GZIP压缩反回数据1、初识gzip2、gzip是什么,可以干什么?3、Spr

Spring Boot 集成 Quartz并使用Cron 表达式实现定时任务

《SpringBoot集成Quartz并使用Cron表达式实现定时任务》本篇文章介绍了如何在SpringBoot中集成Quartz进行定时任务调度,并通过Cron表达式控制任务... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启动 Sprin

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文