首先下载memcached的windows版本和java客户端jar包,目前最新版本是memcached-1.2.1-win32.zip和java_memcached-release_2.6.3.zip,分别解压后即可!首先是安装运行memcached服务器,我们将memcached-1.2.1-win32.zip解压后改名memcached放到e盘,进入其目录,然后运行如下命令:
e:\cd memcached
e:\memcached >memcached.exe -d install -l 127.0.0.1 -m 1024 -c 2048
打开服务列表,可以看到memcached已经在上面可,如果没有启动,则手动启动一下。
或者命令启动e:\memcached >memcached.exe -d start
启动完毕可以关闭cmd窗口
memcached.exe -d install -l 127.0.0.1 -m 1024 -c 2048:是安装在本机,分配1024M内存,使用默认端口11211,允许连接数量2028和-d以守护进行运行。执行完毕后,我们就可以在任务管理器中见到memcached.exe这个进程了。
使用telnet命令 验证缓存服务器是否可用。
开始什么都不显示,回车后输入命令 stats 查看统计信息,如下图,说明服务器运作正常。
三、参数介绍
1、 以上的安装和启动给了一些参数,在安装时可设置如下参数:
-p 设置端口号(默认不设置为: 11211)-l 绑定地址(默认:所有都允许,无论内外网或者本机更换IP,有安全隐患,若设置为127.0.0.1就只能本机访问)
-d 独立进程运行:
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 绑定使用指定用于运行进程
-m 允许最大内存用量,单位M (默认: 64 MB)
-P 将PID写入文件,可以使得后边进行快速进程终止,需要与-d 一起使用
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助
如:“memcached -d install -l 127.0.0.1 -m 1024 -c 2048 -p 22222”
好了,我们的服务器已经正常运行了,
接下来我们编写一个工具类MemcachedUtils.java。里面封装了一些memcached的方法,这些方法都是基于 java_memcached-release2.6.3.jar进行包装的, 使用它与spring整合可以方便我们在项目中使用。
本工具类的原作者是:http://blog.csdn.net/yin_jw/article/details/32331453
程序如下:-
package com.test.utils;
spring-memcached.xml 配置文件
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.log4j.Logger;
import com.danga.MemCached.MemCachedClient;
public class MemcachedUtils {
private static final Logger logger = Logger.getLogger(MemcachedUtils.class);
private static MemCachedClient cachedClient;
static {
if (cachedClient == null)
cachedClient = new MemCachedClient("memcachedPool");//注入的是spring-memcached中的实例
}
private MemcachedUtils() {}
/**
* 向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。
*
* @param key
* 键
* @param value
* 值
* @return
*/
public static boolean set(String key, Object value) {
return setExp(key, value, null);
}
/**
* 向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。
*
* @param key
* 键
* @param value
* 值
* @param expire
* 过期时间 New Date(1000*10):十秒后过期
* @return
*/
public static boolean set(String key, Object value, Date expire) {
return setExp(key, value, expire);
}
/**
* 向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。
*
* @param key
* 键
* @param value
* 值
* @param expire
* 过期时间 New Date(1000*10):十秒后过期
* @return
*/
private static boolean setExp(String key, Object value, Date expire) {
boolean flag = false;
try {
flag = cachedClient.set(key, value, expire);
} catch (Exception e) {
// 记录Memcached日志
MemcachedLog.writeLog("Memcached set方法报错,key值:" + key + "\r\n" + exceptionWrite(e));
}
return flag;
}
/**
* 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。
*
* @param key
* 键
* @param value
* 值
* @return
*/
public static boolean add(String key, Object value) {
return addExp(key, value, null);
}
/**
* 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。
*
* @param key
* 键
* @param value
* 值
* @param expire
* 过期时间 New Date(1000*10):十秒后过期
* @return
*/
public static boolean add(String key, Object value, Date expire) {
return addExp(key, value, expire);
}
/**
* 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。
*
* @param key
* 键
* @param value
* 值
* @param expire
* 过期时间 New Date(1000*10):十秒后过期
* @return
*/
private static boolean addExp(String key, Object value, Date expire) {
boolean flag = false;
try {
flag = cachedClient.add(key, value, expire);
} catch (Exception e) {
// 记录Memcached日志
MemcachedLog.writeLog("Memcached add方法报错,key值:" + key + "\r\n" + exceptionWrite(e));
}
return flag;
}
/**
* 仅当键已经存在时,replace 命令才会替换缓存中的键。
*
* @param key
* 键
* @param value
* 值
* @return
*/
public static boolean replace(String key, Object value) {
return replaceExp(key, value, null);
}
/**
* 仅当键已经存在时,replace 命令才会替换缓存中的键。
*
* @param key
* 键
* @param value
* 值
* @param expire
* 过期时间 New Date(1000*10):十秒后过期
* @return
*/
public static boolean replace(String key, Object value, Date expire) {
return replaceExp(key, value, expire);
}
/**
* 仅当键已经存在时,replace 命令才会替换缓存中的键。
*
* @param key
* 键
* @param value
* 值
* @param expire
* 过期时间 New Date(1000*10):十秒后过期
* @return
*/
private static boolean replaceExp(String key, Object value, Date expire) {
boolean flag = false;
try {
flag = cachedClient.replace(key, value, expire);
} catch (Exception e) {
MemcachedLog.writeLog("Memcached replace方法报错,key值:" + key + "\r\n" + exceptionWrite(e));
}
return flag;
}
/**
* get 命令用于检索与之前添加的键值对相关的值。
*
* @param key
* 键
* @return
*/
public static Object get(String key) {
Object obj = null;
try {
obj = cachedClient.get(key);
} catch (Exception e) {
MemcachedLog.writeLog("Memcached get方法报错,key值:" + key + "\r\n" + exceptionWrite(e));
}
return obj;
}
/**
* 删除 memcached 中的任何现有值。
*
* @param key
* 键
* @return
*/
public static boolean delete(String key) {
return deleteExp(key, null);
}
/**
* 删除 memcached 中的任何现有值。
*
* @param key
* 键
* @param expire
* 过期时间 New Date(1000*10):十秒后过期
* @return
*/
public static boolean delete(String key, Date expire) {
return deleteExp(key, expire);
}
/**
* 删除 memcached 中的任何现有值。
*
* @param key
* 键
* @param expire
* 过期时间 New Date(1000*10):十秒后过期
* @return
*/
private static boolean deleteExp(String key, Date expire) {
boolean flag = false;
try {
flag = cachedClient.delete(key, expire);
} catch (Exception e) {
MemcachedLog.writeLog("Memcached delete方法报错,key值:" + key + "\r\n" + exceptionWrite(e));
}
return flag;
}
/**
* 清理缓存中的所有键/值对
*
* @return
*/
public static boolean flashAll() {
boolean flag = false;
try {
flag = cachedClient.flushAll();
} catch (Exception e) {
MemcachedLog.writeLog("Memcached flashAll方法报错\r\n" + exceptionWrite(e));
}
return flag;
}
/**
* 返回异常栈信息,String类型
*
* @param e
* @return
*/
private static String exceptionWrite(Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.flush();
return sw.toString();
}
/**
*
* @ClassName: MemcachedLog
* @Description: Memcached日志记录
* @author yinjw
* @date 2014-6-18 下午5:01:37
*
*/
private static class MemcachedLog {
private final static String MEMCACHED_LOG = "D:\\memcached.log";
private final static String LINUX_MEMCACHED_LOG = "/usr/local/logs/memcached.log";
private static FileWriter fileWriter;
private static BufferedWriter logWrite;
// 获取PID,可以找到对应的JVM进程
private final static RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
private final static String PID = runtime.getName();
/**
* 初始化写入流
*/
static {
try {
String osName = System.getProperty("os.name");
if (osName.indexOf("Windows") == -1) {
fileWriter = new FileWriter(MEMCACHED_LOG, true);
} else {
fileWriter = new FileWriter(LINUX_MEMCACHED_LOG, true);
}
logWrite = new BufferedWriter(fileWriter);
} catch (IOException e) {
logger.error("memcached 日志初始化失败", e);
closeLogStream();
}
}
/**
* 写入日志信息
*
* @param content
* 日志内容
*/
public static void writeLog(String content) {
try {
logWrite.write("[" + PID + "] " + "- [" + new SimpleDateFormat("yyyy年-MM月-dd日 hh时:mm分:ss秒").format(new Date().getTime()) + "]\r\n"
+ content);
logWrite.newLine();
logWrite.flush();
} catch (IOException e) {
logger.error("memcached 写入日志信息失败", e);
}
}
/**
* 关闭流
*/
private static void closeLogStream() {
try {
fileWriter.close();
logWrite.close();
} catch (IOException e) {
logger.error("memcached 日志对象关闭失败", e);
}
}
}
}<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- 客户端:java_memcached-release_2.6.3 -->
<bean id="memcachedPool" class="com.danga.MemCached.SockIOPool" factory-method="getInstance" init-method="initialize" lazy-init="false" destroy-method="shutDown">
<constructor-arg>
<value>memcachedPool</value>
</constructor-arg>
<!-- 可以设置多个memcached服务器 -->
<property name="servers">
<list>
<value>127.0.0.1:11211</value>
</list>
</property>
<!-- 每个服务器初始连接数 -->
<property name="initConn">
<value>20</value>
</property>
<!-- 每个服务器最小连接数 -->
<property name="minConn">
<value>20</value>
</property>
<!-- 每个服务器最大连接数 -->
<property name="maxConn">
<value>1000</value>
</property>
<!-- 主线程睡眠时间 -->
<property name="maintSleep">
<value>30000</value>
</property>
<!-- TCP/Socket的参数,如果是true在写数据时不缓冲,立即发送出去参数 -->
<property name="nagle">
<value>false</value>
</property>
<!-- 连接超时/阻塞读取数据的超时间是 -->
<property name="socketTO">
<value>3000</value>
</property>
</bean>
<bean id="memcachedClient" class="com.danga.MemCached.MemCachedClient" >
<constructor-arg>
<value>memcachedPool</value>
</constructor-arg>
</bean>
</beans>
- @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( "classpath:spring-memcached.xml")
public class MemcachedTest {
@Test
public void testInsert(){
User user = new User("honghong","19","man"); //存储对象要序列化
MemcachedUtil.add("xxx",user);
}
@Test
public void testGet(){
// User user = (User)MemcachedUtil.get("xiao");
User user2 = (User)MemcachedUtil.get("xxx");
System.out.println("输出:" + user2.getName()+user2.getAge());
}
} - 运行结果:
- com.danga.MemCached.MemCachedClient Tue Jan 31 16:28:39 CST 2012 - Storing with native handler...
- com.danga.MemCached.MemCachedClient Tue Jan 31 16:28:39 CST 2012 - ++++ memcache cmd (result code): add hello 0 0 20
- (NOT_STORED)
- com.danga.MemCached.MemCachedClient Tue Jan 31 16:28:39 CST 2012 - ++++ data not stored in cache for key: hello
- 输出: honghong19
其实呢 我们完全可以不用建memcachedutil这个类,在service层直接通过注解注入memCachedClient实例就可
2. 使用telnet进行连接
现在我将在Windows7 下使用telnet连接安装好的memcached
a. 开启Windows7 控制台,输入: telnet memcached_IP memcached_PORT
3. memcached 的操作指令b. 按Enter后,进入如下的页面:按Enter后,如果正常连接,会显示如此图所示的黑框框,输入任何东西都不会显现出来,看不到任何东西,这是因为Win7 中将telnet 回显功能关闭了,这时候需要手动设置回显。
c. 对当前框同时按下 “CTRL ”和“]” 健,将进入如下页面:
d. 输入 “set localecho”,开启回显telnet回显功能
e. 按下Enter键,进入telnet 交互界面,这时候用户可以看到自己的输入了,并且可以看到连接的memcached返回的交互信息:
- #向memcached存放一个key为variable、值为“louis”的键值对
- set variable1 0 0 5
- #取出key为variable的值
- get variable
至此,你就可以使用你的memcached啦。
memcached本质上就是内存中的一个Map键值对集合,对于这个Map基本操作有以下几个:
- 基本数据操作
- set 设置指定键值对
- add 若当前键值Key不存在,添加指定键值对
- replace 若当前键值Key存在,更新当前Value值
- get 获取指定键值对
- delete 删除指定键值对
- 高级数据操作
- gets 获取键值key对应的值,返回信息中携带版本号
- cas 指定版本号对键值key进行赋值,版本号不匹配,允许赋值
- 缓存管理操作
- stats 统计当前memcached 的数据信息。
- flush_all 清空当前memcached 服务的所有缓存数据
4. 操作memcached 的客户端
java如果想要与memcached联合使用的话,需要使用memcached的客户端,这是网友们的叫法。其实就是jar包。这些jar包帮我们封装好了一些方法,避免我们自己再去实现复杂的操作了。
目前我看到有三个客户端:
-
- java_memcached-release --->:danga的,我也不知道这是什么组织……,但这个客户端比较老牌的了,应用的还是挺广泛的。
- alisoft-xplatform-asf-cache --->:阿里的
- XMemcached --->:oschina上看到的,貌似是纯国产啊,应用的还是挺广泛的~