前言:之前项目中,有需求在不同语言开发的服务器之间做数据共享,从而引入了Memcached技术,在实际使用中,Memcached除了作为数据共享的用途外,还用作数据库前段存储。但是,查阅相关资料发现,用java操作Memcached服务器的资料并不是太多,偶尔查到的资料也不能运行,踩了很多坑,因此总结项目中的使用经验,输出基本demo。
本篇文章重点关注以下问题:
- Memcached简介,及对安装的简要说明;
- Memcached几种客户端介绍;
- Memcached的Demo输出;
1. Memcached简介,及对安装的简要说明;
1.1 Memcached简介
Memcached是一款开源、高性能、分布式内存对象缓存系统,可应用各种需要缓存的场景,其主要目的是通过降低对Database的访问来加速web应用程序。它是一个基于内存的“键值对”存储,用于存储数据库调用、API调用或页面引用结果的直接数据,如字符串、对象等。
首先来看一个Memcached的基本使用场景:
许多Web应用都将数据保存到RDBMS(关系型数据库管理系统)中,应用服务器从中读取数据并在浏览器中显示。 但随着数据量的增大、访问的集中,就会出现RDBMS的负担加重、数据库响应恶化、 网站显示延迟等重大影响。这时就该Memcached大显身手了。Memcached是高性能的分布式内存缓存服务器。 一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、 提高可扩展性。
总结Memcached的使用特点:
- 简单key/value存储:服务器不关心数据本身的意义及结构,只要是可序列化数据即可。存储项由“键、过期时间、可选的标志及数据”四个部分组成。
- 功能的实现一半依赖于客户端,一半基于服务器端:客户负责发送存储项至服务器端、从服务端获取数据以及无法连接至服务器时采用相应的动作;服务端负责接收、存储数据,并负责数据项的超时过期。
- 各服务器间彼此无视,不在服务器间进行数据同步。所有分布式功能由客户端实现。
- O(1)的执行效率。
- 清理超期数据,默认情况下,Memcached是一个LRU缓存,同时,它按事先预订的时长清理超期数据。但事实上,Memcached不会删除任何已缓存数据,只是在其过期之后不再为客户所见;而且,Memcached也不会真正按期限清理缓存,而仅是当get命令到达时检查其时长。
1.2 Memcached安装过程
步骤五:启动Memcached:memcached.exe -d start,查看是否启动:
2. Memcached几种客户端介绍
- memcached client for java:官方提供的基于传统阻塞io由Greg Whalin维护的客户端;
- spymemcached:基于java nio的Spymemcached;
- xmemcached:国人开发的,貌似各方面性能指标都很优秀;
由于memcached client for java发布了新版本,性能上有所提高,并且运行稳定,所以建议使用memcached client for java。
XMemcached目前也使用得比较广泛,而且有较详细的中文API文档,具有如下特点:高性 能、支持完整的协议、支持客户端分布、允许设置节点权重、动态增删节点、支持JMX、与Spring框架和Hibernate-memcached的集 成、客户端连接池、可扩展性好等。
3. Demo输出
3.1 memcached client for java
https://cloud.github.com/downloads/gwhalin/Memcached-Java-Client/java_memcached-release_2.6.6.zip下载解压后,将里面所有的jar包添加到项目的构建路径里。
先上封装的工具类:
package com.wj.MemCachedClient;
import java.util.Date;
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;
public class MemcachedHelper {
// 构建缓存客户端
private static MemCachedClient cachedClient = new MemCachedClient();
// 单例模式实现客户端管理类
private static MemcachedHelper INSTANCE = new MemcachedHelper();
private MemcachedHelper() {}
/**
* 获取缓存管理器唯一实例
* @param servers 设置缓存服务器列表,当使用分布式缓存的时,可以指定多个缓存服务器。(这里应该设置为多个不同的服务器)
* @return
*/
public static MemcachedHelper getInstance(String[] servers) {
// 初始化SockIOPool,管理memcached的连接池
SockIOPool pool = SockIOPool.getInstance();
pool.setServers(servers);
pool.setFailover(true);
pool.setInitConn(10); // 设置初始连接
pool.setMinConn(5);// 设置最小连接
pool.setMaxConn(250); // 设置最大连接
pool.setMaxIdle(1000 * 60 * 60 * 3); // 设置每个连接最大空闲时间3个小时
pool.setMaintSleep(30);
pool.setNagle(false);
pool.setSocketTO(3000);
pool.setAliveCheck(true);
pool.initialize();
return INSTANCE;
}
public void add(String key, Object value) {
cachedClient.set(key, value);
}
public void add(String key, Object value, int milliseconds) {
cachedClient.set(key, value, milliseconds);
}
public void remove(String key) {
cachedClient.delete(key);
}
@SuppressWarnings("deprecation")
public void remove(String key, int milliseconds) {
cachedClient.delete(key, milliseconds, new Date());
}
public void update(String key, Object value, int milliseconds) {
cachedClient.replace(key, value, milliseconds);
}
public void update(String key, Object value) {
cachedClient.replace(key, value);
}
public Object get(String key) {
return cachedClient.get(key);
}
public static void main(String[] args) {
//将对象加入到memcached缓存
cachedClient.add("keke", "This is a test String");
//从memcached缓存中按key值取对象
String result = (String) cachedClient.get("keke");
System.out.println(result);
}
}
调用demo:
package com.wj.MemCachedClient;
public class Main {
public static void main(String[] args) {
String[] servers = { "127.0.0.1:11211"};
MemcachedHelper memcachedHelper = MemcachedHelper.getInstance(servers);
memcachedHelper.add("key", "value");
String result = (String) memcachedHelper.get("key");
System.out.println(result);
}
}
3.2 spymemcached
package com.wj.spymemcached;
import java.io.IOException;
import java.net.InetSocketAddress;
import net.spy.memcached.MemcachedClient;
public class MemcachedHelper {
// 缓存客户端
private static MemcachedClient memcacheCient;
// Manager管理对象,单例模式
private static MemcachedHelper INSTANCE = new MemcachedHelper();
private MemcachedHelper() {}
public static MemcachedHelper getInstance(InetSocketAddress... addresses) {
try {
memcacheCient = new MemcachedClient(new InetSocketAddress(
"127.0.0.1", 11211));
} catch (IOException e) {
e.printStackTrace();
}
return INSTANCE;
}
public void add(String key, Object value, int milliseconds) {
memcacheCient.add(key, milliseconds, value);
}
public void add(String key, Object value) {
memcacheCient.add(key, 3600, value);
}
public void remove(String key, int milliseconds) {
memcacheCient.delete(key);
}
public void remove(String key) {
memcacheCient.delete(key);
}
public void update(String key, Object value, int milliseconds) {
memcacheCient.replace(key, milliseconds, value);
}
public void update(String key, Object value) {
memcacheCient.replace(key, 3600, value);
}
public Object get(String key) {
return memcacheCient.get(key);
}
}
下面是调用demo:
package com.wj.spymemcached;
import java.net.InetSocketAddress;
public class Main {
public static void main(String[] args) {
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 11211);
MemcachedHelper memcachedHelper = MemcachedHelper.getInstance(address);
memcachedHelper.add("key1", "value1");
String result = (String) memcachedHelper.get("key1");
System.out.println(result);
}
}
3.3 xmemcached
Xmemcached的官方网址是:http://code.google.com/p/xmemcached/。
尚未研究过,有待后续添加...
代码地址:http://pan.baidu.com/s/1pLDLip9, ,密码:8dj6
有用的学习网址:http://www.runoob.com/memcached/memcached-tutorial.html