Java之XMemcached使用及源码详解

本文主要讲述如何使用XMemcached客户端与Memcached服务端进行交互。通过XMemcached的API调用与Memcached的set/get命令对比及跟踪XMemcached源码,使大家对XMemcached的API有更深层次的理解,能够从底层上去了解其工作原理,从而能在项目中进行一些针对性的接口封闭及优化工作。 

是叫Memcache还是Memcached?

网上有种说法是:Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名。我又查了Memcache的官网,home页一直引用的是Memcached。姑且不论该叫什么名称合适,在这里统一称呼为Memcached,仅代表我的个人习惯。

Memcached简介

言归正题,Memcached是分布式高性能内存级别的对象缓存系统,并且是开源免费项目。它的所有key-value数据全部放在内存中,这是其高效的一个原因,同时也意味着系统关闭时,全部数据就会丢失。利用Memcached作用缓存系统,可以减少动态网站数据库查询次数,提升网站性能,常作为web2.0网站缓存解决方案。Memcached客户端提供多种语言API支持,像C/C++、Perl、PHP、Java、C#、Ruby等。

      Memcached的Java客户端目前有3个

Memcached Client for Java 比 SpyMemcached更稳定、更早、更广泛;

SpyMemcached 比 Memcached Client for Java更高效;

XMemcached 比 SpyMemcache并发效果更好;

前两个客户端的使用,这里不做详述。

分三部分讲解XMemcached客户端

XMemcached客户端使用演示

set/get方法源码追踪

对比Memcached的set/get命令

一、XMemcached客户端使用演示

本人是用Maven构建的项目,为了使用XMemcached,需要在pom.xml中加入

<dependency> <groupId>com.googlecode.xmemcached</groupId> <artifactId>xmemcached</artifactId> <version>1.4.3</version> </dependency>

XMemcached使用示例Demo如下

public static void main(String[] args) throws IOException { MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses("127.0.0.1:11211")); MemcachedClient memcachedClient = builder.build(); try { memcachedClient.set("key", 0, "Hello World!"); String value = memcachedClient.get("key"); System.out.println("key值:" + value); } catch (Exception e) { e.printStackTrace(); } try { memcachedClient.shutdown(); } catch (IOException e) { e.printStackTrace(); } }

接下来详细追踪下这两个方法的源码

二、set/get方法源码追踪 1.set

大家可以用过debug模式,一步步追踪set及get过程,具体过程不演示了,先直接列出set方法大概的源码调用过程如下(中间可能省略了某些方法调用)

XMemcachedClient.set() XMemcachedClient.sendCommand() MemcachedConnector.send() AbstractSession.write() MemcachedTCPSession.wrapMessage() TextStoreCommand.encode() TextStoreCommand.encodeValue() SerializingTranscoder.encode() BaseSerializingTranscoder.serialize()

先是调用XMemcacheClient.set(final String key, final int exp, final Object value)方法,key形参对应字符串“key”,exp形参对应整数0(表达缓存永不过期),value形参对应字符串“Hello World!”。经过上述一系列方法调用,最终调用到SerializingTranscoder.encode(Object o)方法,此时形参o接收到的实参值就是set的字符串“Hello World!”,该方法体代码如下:

public final CachedData encode(Object o) { byte[] b = null; int flags = 0; if (o instanceof String) { b = encodeString((String) o); } else if (o instanceof Long) { if (this.primitiveAsString) { b = encodeString(o.toString()); } else { b = this.transcoderUtils.encodeLong((Long) o); } flags |= SPECIAL_LONG; } else if (o instanceof Integer) { if (this.primitiveAsString) { b = encodeString(o.toString()); } else { b = this.transcoderUtils.encodeInt((Integer) o); } flags |= SPECIAL_INT; } else if (o instanceof Boolean) { if (this.primitiveAsString) { b = encodeString(o.toString()); } else { b = this.transcoderUtils.encodeBoolean((Boolean) o); } flags |= SPECIAL_BOOLEAN; } else if (o instanceof Date) { b = this.transcoderUtils.encodeLong(((Date) o).getTime()); flags |= SPECIAL_DATE; } else if (o instanceof Byte) { if (this.primitiveAsString) { b = encodeString(o.toString()); } else { b = this.transcoderUtils.encodeByte((Byte) o); } flags |= SPECIAL_BYTE; } else if (o instanceof Float) { if (this.primitiveAsString) { b = encodeString(o.toString()); } else { b = this.transcoderUtils.encodeInt(Float .floatToRawIntBits((Float) o)); } flags |= SPECIAL_FLOAT; } else if (o instanceof Double) { if (this.primitiveAsString) { b = encodeString(o.toString()); } else { b = this.transcoderUtils.encodeLong(Double .doubleToRawLongBits((Double) o)); } flags |= SPECIAL_DOUBLE; } else if (o instanceof byte[]) { b = (byte[]) o; flags |= SPECIAL_BYTEARRAY; } else { b = serialize(o); flags |= SERIALIZED; } assert b != null; if (this.primitiveAsString) { // It is not be SERIALIZED,so change it to string type if ((flags & SERIALIZED) == 0) { flags = 0; } } if (b.length > this.compressionThreshold) { byte[] compressed = compress(b); if (compressed.length < b.length) { if (log.isDebugEnabled()) { log.debug("Compressed " + o.getClass().getName() + " from " + b.length + " to " + compressed.length); } b = compressed; flags |= COMPRESSED; } else { if (log.isDebugEnabled()) { log.debug("Compression increased the size of " + o.getClass().getName() + " from " + b.length + " to " + compressed.length); } } } return new CachedData(flags, b, this.maxSize, -1); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/37fd3759b0df8dbdd6d955eabe9e7ba6.html