Memcached总结文档
memcached简介:
概念:
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。
Memcached与memcache
Memcache是danga的一个项目,最早是LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。
Memcached是以守护程序方式运行于一个或多个服务器中,随时会接收客户端的连接和操作
特点:
memcached作为高速运行的分布式缓存服务器,具有以下的特点。1.协议简单:memcached的服务器客户端通信并不使用复杂的XML等格式,而使用简单的基于文本行的协议。因此,通过telnet也能在memcached上保存数据、取得数据。
2. 基于libevent的事件处理:ibevent是个程序库,它将Linux的epoll、BSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥O(1)的性能。memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能。
3.存储方式:memcached默认情况下采用了名为Slab Allocatoion的机制分配,管理内存。内容容量达到指定值之后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。
4.通信分布式memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。而是基于客户端实现的。
Memcached运行原理示意图
linux安装memcached服务端
下载memcached客户端:另外,Memcache用到了libevent这个库用于Socket的处理,所以还需要安装libevent,如果你的系统已经安装了libevent,可以不用安装如果没有也必须下载安装。
1.在linux中打开终端:分别把memcached和libevent下载回来,放到 /tmp 目录下:
Linux终端输入语句:
# cd /tmp 进入tmp文件夹
# wget http://www.danga.com/memcached/dist/memcached-1.2.0.tar.gz
# wget http://www.monkey.org/~provos/libevent-1.2.tar.gz
自动下载memcached-1.2.0.tar.gz和libevent-1.2.tar.gz
如在虚拟机linux中无法下载,看错误中的解决方案
2.先安装libevent:依次执行下列语句
# tar zxvf libevent-1.2.tar.gz
# cd libevent-1.2
# ./configure –prefix=/usr
# make
# make install
3 测试libevent是否安装成功:
# ls -al /usr/lib | grep libevent
如输出一下信息则安装成功
4.安装memcached,安装时需要指定libevent的安装位置:(顺序执行以下语句)
# cd /tmp
# tar zxvf memcached-1.2.0.tar.gz
# cd memcached-1.2.0
# ./configure –with-libevent=/usr
# make
# make install
安装完成后会把memcached放到 /usr/local/bin/memcached
5.测试memcached是否安装成功
# ls -al /usr/local/bin/mem*
如果输出一下信息,则安装成功
启动memcached服务端
# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.141.64 -p 12000 -c 256 -P /tmp/memcached.pid
语句中各个参数的含义
如果要结束memcached,则执行: # kill ‘cat /tmp/memcached.pid’
查看memcached运行状态
ps -ef|grep memcached
注意:可以启动多个守护进程,不过端口不能重复。
测试memcached
按照下图执行语句,如果可以输出信息,则表示正常
安装时遇到错误
下载时无法下载
解决方案:
在windows里通过浏览器直接下载,然后通过ssh工具直接复制到 /tmp下
步骤:1.在linux里输入下面语句设置ip
ifconfig eth0 ip地址
2.在windows下通过ssh连接linux
连接成功之后点击如下按钮
会出现
在本地window中找到下载的文件复制到linux中的/tmp目录下
启动memcached时遇到的错:
解决方案
Memcached缓存简单字符串
1.引入commons-pool-1.5.6.jar,java_memcached-release_2.5.1.jar,slf4j-api-1.6.1.jar,slf4j-simple-1.6.1.jar
同时导入junit 包和 log4j包,若不使用junit测试或者打印日志信息可不导入
2.创建memcached工具类:
public class MemcachedUtil {
//log4j
private static Logger logger = Logger.getLogger(MemcachedUtil.class);
//实例化memcached客户端
public static MemCachedClient mcc = null;
//SockIOPool是Memcached客户端提供的一个套接字连接池,通俗讲,就是与Memcached服务器端交换数据的对象。
private static SockIOPool pool = null;
//初始调用init方法
static {
init();
}
/**
* 初始化连接池
*/
public static void init() {
String sockPoolName = "MEM_CAHCE";
String serverlist = "";
//初始连接数
int initConn = 5;
//最小连接数
int minConn = 5;
//最大连接数
int maxConn = 50;
Properties properties = new Properties();
try {
//加载配置文件
properties.load(new FileInputStream(MemcachedUtil.class.getResource("/test/memcache.properties").getFile()));
sockPoolName = properties.getProperty("memcache.poolName", sockPoolName);
serverlist = properties.getProperty("memcache.serverlist", serverlist);
initConn = Integer.parseInt(properties.getProperty("memcache.initConn", "5"));
minConn = Integer.parseInt(properties.getProperty("memcache.minConn", "5"));
maxConn = Integer.parseInt(properties.getProperty("memcache.maxConn", "50"));
} catch (IOException e) {
logger.warn("not found finle memcache.properties in classpath", e);
}
logger.info("Initializing memcached pool");
if (pool == null) {
try {
pool = SockIOPool.getInstance(sockPoolName);
pool.setServers(serverlist.split(","));
if (!pool.isInitialized()) {
pool.setInitConn(initConn);
pool.setMinConn(minConn);
pool.setMaxConn(maxConn);
pool.setMaintSleep(30);
pool.setNagle(false);
//最大处理时间
pool.setSocketTO(60 * 60);
//设置TCP参数,连接超时
pool.setSocketConnectTO(0);
//初始化并启动连接池
pool.initialize();
}
} catch (Exception ex) {
logger.error(ex.getMessage());
}
}
if (mcc == null) {
mcc = new MemCachedClient(sockPoolName);
mcc.setClassLoader(MemcachedUtil.class.getClassLoader());
mcc.setCompressEnable(false);
mcc.setCompressThreshold(0);
}
}
/**
* 关闭连接池
*/
public static void closePool() {
pool.shutDown();
mcc = null;
pool = null;
logger.info("Memcached pool closed");
}
/**
* 设置缓存
*
* @param key 键
* @param obj 值
*/
public static boolean set(String key, Object obj) {
try {
return mcc.set(key, obj);
} catch (Exception e) {
logger.error("Pool set error!");
e.printStackTrace();
}
return false;
}
/**
* 设置缓存
*
* @param key 键
* @param obj 值
*/
public static boolean set(String key, Object obj, long time) {
try {
return mcc.set(key, obj, new Date(time));
} catch (Exception e) {
logger.error("Pool set error!");
e.printStackTrace();
}
return false;
}
/**
* 设置缓存
*
* @param key 键
* @param obj 值
* @param time 缓存时间(毫秒)
*/
public static boolean set(String key, Serializable obj, long time) {
try {
return mcc.set(key, obj, new Date(time));
} catch (Exception e) {
logger.error("Pool set error!");
e.printStackTrace();
}
return false;
}
public static void replace(String key, Serializable value, long cachelTime) {
try {
mcc.replace(key, value, new Date(cachelTime));
} catch (Exception e) {
logger.error(" pool set error!");
}
}
/**
* 获取缓存
*
* @param key 键
* @return 值
*/
public static Object get(String key) {
Object result = null;
try {
result = mcc.get(key);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 缓存数值
*
* @param key 键
* @param count 数值
*/
public static void setCounter(String key, long count) {
try {
mcc.storeCounter(key, count);
} catch (Exception e) {
logger.error("Pool setCounter error!");
}
}
/**
* 缓存的数值加1
*
* @param key 键
*/
public static void addCounter(String key) {
try {
mcc.incr(key);
} catch (Exception e) {
logger.error("Pool setCounter error!");
}
}
/**
* 增加缓存数值
*
* @param key 键
* @param addValue 增加的值
*/
public static void addCounter(String key, long addValue) {
try {
mcc.incr(key, addValue);
} catch (Exception e) {
logger.error(" pool setCounter error!");
}
}
/**
* 获取缓存数值
*
* @param key 键
* @return 值
*/
public static long getCounter(String key) {
long result = 0;
try {
result = mcc.getCounter(key);
} catch (Exception e) {
logger.error(e.getMessage());
}
return result;
}
/**
* 删除缓存
*
* @param key 键
*/
public static boolean delete(String key) {
try {
return mcc.delete(key);
} catch (Exception e) {
logger.error(e.getMessage());
}
return false;
}
/**
* 删除缓存数值
*
* @param key 键
*/
public static long deleteCounter(String key) {
try {
return mcc.decr(key);
} catch (Exception e) {
logger.error(" pool setCounter error!");
}
return 0;
}
}
数据写入操作方法的解释:
set方法
将数据保存到cache服务器,如果保存成功则返回true
如果cache服务器存在同样的key,则替换之
set有5个重载方法,key和value是必须的参数,还有过期时间,hash码,value是否字符串三个可选参数
add方法
将数据添加到cache服务器,如果保存成功则返回true
如果cache服务器存在同样key,则返回false
add有4个重载方法,key和value是必须的参数,还有过期时间,hash码两个可选参数
· replace方法
将数据替换cache服务器中相同的key,如果保存成功则返回true
如果cache服务器不存在同样key,则返回false
replace有4个重载方法,key和value是必须的参数,还有过期时间,hash 码两个可选参数
其中过期时间的单位为毫秒
数据读取方法的解释:
cache数据读取操作方法
使用get方法从cache服务器获取一个数据
3.创建测试用例:
//调用工具类的set方法 往memcached里添加值(设置过期时间的时候不能低于1000毫秒)
MemcachedUtil.set("hello", "world", 1000);
//调用工具类的get方法根据键获取值
Object hello = MemcachedUtil.get("hello");
//直接输出没有睡眠时间,即不超过缓存的过期时间System.out.println(hello+"--------------------------------");
//调用睡眠方法使程序停止运行2000毫秒
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//再次调用get方法
Object hello2 = MemcachedUtil.get("hello");
System.out.println(hello2+"--------------------------------");
Assert.assertEquals("world", hello);
Memcached缓存实体对象
1.创建JavaBean 对象并实现Serializable否则会缓存不到memcached中其他步骤与缓存简单字符一样
设置多个端口进行缓存:
在配置文件中,在serverlist中设置多个端口,不同端口之间用,分割
附(配置文件):memcached.properties
memcache.poolName=MEM_CAHCE
#memcache.serverlist=127.0.0.1:11211
memcache.serverlist=192.168.192.128:12244,192.168.192.128:12233
memcache.initCon=5
memcache.minConn=5
memcache.maxConn=508
遇错总结:
1.在windows中使用Java程序连接linux时必须保证linux的防火墙是关闭的否则会出现如下错误
com.schooner.MemCached.SchoonerSockIOPool Thu Aug 21 00:09:00 CST 2014 - ++++ failed to get SockIO obj for: 192.168.192.128:1223
com.schooner.MemCached.SchoonerSockIOPool Thu Aug 21 00:09:00 CST 2014 - ++++ failed to create connection to: 192.168.192.128:1223 -- only 0 created.
com.schooner.MemCached.SchoonerSockIOPool Thu Aug 21 00:09:01 CST 2014 - ++++ failed to get SockIO obj for: 192.168.192.128:1223
设置过期时间的时候必须保证过期时间大于1000毫秒,否则设置过期时间不起作用