首先下载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
或者命令启动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)
如:“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; 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); } } } }spring-memcached.xml 配置文件
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"> class="com.danga.MemCached.SockIOPool" factory-method="getInstance" init-method="initialize" lazy-init="false" destroy-method="shutDown"> memcachedPool
127.0.0.1:11211 20 20 1000 30000 false 3000 class="com.danga.MemCached.MemCachedClient" > memcachedPool
其实呢 我们完全可以不用建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 服务的所有缓存数据
基本数据操作:set、add、replace操作set、add、replace操作的格式相同,如下图所示:
注意:
1. set、add、replace 操作指令需要输入两行才能完成,第一行是指令前段,第二行是value值;
2. set、add、replace操作指定的字节数
参数的大小要和第二行输入的字符串的个数保持完全相同 ,否则将会报:“CLIENT_ERROR bad data chunk”
1、set操作
set
命令用于向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。如上图所示,如果set指令正确执行,memcached将会返回一个“STORED”信息,表示该指令被正确处理、已经将缓存数据放到了memcached中。
2. add操作
向缓存中添加一个键值对,如果该键值key在缓存中尚未存在,则该键值对将添加到memcached缓存中;如果该键值已经存在了,那么保留以前的值,向客户端返回“NOT STORED”
3. replace操作
仅当键已经存在时,
基本数据操作:get、delete操作replace
命令才会替换缓存中的键。如果缓存中不存在键,那么您将从 memcached 服务器接受到一条NOT_STORED 响应。get和delete操作的格式比较简单,格式如下:
4. get 操作
从缓存中根据key值取数据。如果缓存中有数据,这返回该数据;如果缓存中没有,则什么都不返回。
5. delete 操作
delete
命令用于删除 memcached 中的任何现有值。您将使用一个键调用delete
,如果该键存在于缓存中,则删除该值。如果不存在,则返回一条NOT_FOUND 消息。
高级数据操作:gets、cas操作6. gets操作
gets操作和get操作的功能差不多,但它比get都返回一个信息:即这个键值对的“版本号”,版本号是使用64位的整形值表示的。memcached在以键值对进行存储的时候,会统计键值key的使用情况,每次以键值key进行增、删、改操作键值对的时候,该键值key代表的键值对的版本都会递增。
操作形式为:
gets key
操作如下:
7. cas操作
cas操作是(check and set)的缩写,在针对某个键值key设置对应的值的时候,要加上键值key目前的版本号。如果你指定的版本号比和键值Key的实际版本号不一致时,不会进行set操作,返回“EXISTS”提示。
cas 的操作语法如下:
cas key flags expiration_time length version
管理操作:stats、flush_all 操作8. stats
stats 是statistics单词的拼写,即统计的意思。该指令攻击当前memcached服务的各种指标。这些指标跟memcached 的性能和工作状况紧密相关。
9. flush_all
flus_all 指令用于清空memcached中所有的键值对。
4. 操作memcached 的客户端
java如果想要与memcached联合使用的话,需要使用memcached的客户端,这是网友们的叫法。其实就是jar包。这些jar包帮我们封装好了一些方法,避免我们自己再去实现复杂的操作了。
目前我看到有三个客户端: