Memcache是什么
Memcache是danga.com的一个项目,最早视为LiveJournal服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。
它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。
为什么会有Memcache和memcached两种名称?
其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名
Memcache官方网站也由 http://www.danga.com/memcached 转为了 http://memcached.org/
Memcache工作原理
首先memcached是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,客户端可以由各种语言编写,目前已知的客户端API包括Perl/PHP/Python/Ruby/Java/C#/C等等。客户端在与memcached服务端连接之后,接下来的事情就是存取对象了,每个被存取的对象都有一个唯一的标识符key,存取操作均通过这个key进行,保存到memcached中的对象实际上是放置内存中的,并不是保存在cache文件中的,这也是为什么maemcached能够如此高效快速的原因。注意,这些对象并不是持久化的,服务停止之后,里边的数据就会丢失。
与许多cache工具类似,Memcached的原理并不复杂。它采用了C/S的模式,在server端启动服务进程,在启动时可以指定监听的ip,自己的端口号,锁使用的内存大小等几个关键参数。一旦启动,服务就一直处于可用状态。Memcached的目前版本是通过C实现,采用了单进程,单线程,异步I/O,基于事件(event_based)的服务方式,使用libevent作为事件通知实现。多个Server可以协同工作,但这些Server之间是没有任何通讯联系的,每个Server只是对自己的数据进行管理。Client端通过指定Server端的ip地址(通过域名应该也可以)。需要缓存的对象或数据是以key->value对的形式保存在Server端。key的值通过hash进行转换,根据hash值把value传递到对应的具体的某个Server上。当需要获取对象数据时,也根据key进行,首先对key进行hash,通过获得的值可以确定它被保存在了哪台Server上,然后再向该Server发出请求。Client端只需要知道保存hash(key)的值在哪台服务器上就可以了。
其实说到底,memcache 的工作就是在专门的机器的内存里维护一张巨大的 hash 表,来存储经常被读写的一些数组与文件,从而极大的提高网站的运行效率。
安装Mac版本
安装memcached
有homebrew的童鞋可以使用
1 |
brew install memcached |
这个命令来安装
没有homebrew的可以直接手动安装
1、去官网http://memcached.org/下载最新的包,然后解压,我这里下的是memcached-1.4.25.tar.gz。
2、因为memcached依赖libevent包,所以我们要先安装libevent,去官网http://libevent.org/下载安装包,然后解压,我这里下的是libevent-2.0.22-stable.tar.gz。
3、进入libevent包的根目录,并执行以下命令:
12 |
$ sudo ./configure --prefix=/usr/local/libevent-2.0.22$ sudo make |
make的最后会提示一个错误,这个错误是因为缺少openssl
1234567 |
bufferevent_openssl.c:60:10: fatal error: 'openssl/bio.h' file not found#include <openssl/bio.h> ^1 error generated.make[2]: *** [bufferevent_openssl.lo] Error 1make[1]: *** [all-recursive] Error 1make: *** [all] Error 2 |
这时候我们继续执行命令:
1234 |
(下面是软连接,前面的一个路径是openssl文件的目录,如果没有可以用homebrew安装openssl,默认安装目录就是/usr/local/Cellar目录,后面的是libevent目录底下的include文件夹下面的openssl目录地址)$ ln -s /usr/local/Cellar/openssl/1.0.2d_1/include/openssl/ ~/Downloads/libevent-2.0.22-stable/include/openssl$ sudo make$ sudo make install |
这时候安装结束后会在/usr/local/ 目录下面多出一个libevent-2.0.22的目录,下面我们来安装memcached
进入memcached的软件包的根目录,执行以下命令:
1234 |
(一定要加上--with-libevent的目录地址,就是刚刚装的地址)$ sudo ./configure --prefix=/usr/local/memcached-1.4.25 --with-libevent=/usr/local/libevent-2.0.22$ sudo make$ sudo make install |
这时候Memcached已经安装完毕了,下面就来介绍如何启动它了。
启动Memcached
因为我们安装的memcached的目录为 /usr/local/memcached-1.4.25
所以我们启动可以直接start
1 |
/usr/local/memcached-1.4.25/bin/memcached start |
当然这运行的时候没有log显示,如果想拥有log的话,可以启动以下命令:
-vv参数调试模式
1 |
sudo /usr/local/memcached-1.4.25/bin/memcached -p 11211 -m 64 -u root -vv |
-d守护进程模式
1 |
sudo /usr/local/memcached-1.4.25/bin/memcached -p 11211 -m 64 -u root -d |
下面是每个参数的说明:
1234567891011121314 |
-p 监听的端口-l 连接的IP地址, 默认是本机-d start 启动memcached服务-d restart 重起memcached服务-d stop|shutdown 关闭正在运行的memcached服务-d install 安装memcached服务-d uninstall 卸载memcached服务-u 以的身份运行 (仅在以root运行的时候有效)-m 最大内存使用,单位MB。默认64MB-M 内存耗尽时返回错误,而不是删除项-c 最大同时连接数,默认是1024-f 块大小增长因子,默认是1.25-n 最小分配空间,key+value+flags默认是48-h 显示帮助 |
附上一个启动后的效果:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
[piqiu@localhost /usr/local/memcached-1.4.25/bin]$./memcached -p 11211 -m 64 -u root -vvslab class 1: chunk size 96 perslab 10922slab class 2: chunk size 120 perslab 8738slab class 3: chunk size 152 perslab 6898slab class 4: chunk size 192 perslab 5461slab class 5: chunk size 240 perslab 4369slab class 6: chunk size 304 perslab 3449slab class 7: chunk size 384 perslab 2730slab class 8: chunk size 480 perslab 2184slab class 9: chunk size 600 perslab 1747slab class 10: chunk size 752 perslab 1394slab class 11: chunk size 944 perslab 1110slab class 12: chunk size 1184 perslab 885slab class 13: chunk size 1480 perslab 708slab class 14: chunk size 1856 perslab 564slab class 15: chunk size 2320 perslab 451slab class 16: chunk size 2904 perslab 361slab class 17: chunk size 3632 perslab 288slab class 18: chunk size 4544 perslab 230slab class 19: chunk size 5680 perslab 184slab class 20: chunk size 7104 perslab 147slab class 21: chunk size 8880 perslab 118slab class 22: chunk size 11104 perslab 94slab class 23: chunk size 13880 perslab 75slab class 24: chunk size 17352 perslab 60slab class 25: chunk size 21696 perslab 48slab class 26: chunk size 27120 perslab 38slab class 27: chunk size 33904 perslab 30slab class 28: chunk size 42384 perslab 24slab class 29: chunk size 52984 perslab 19slab class 30: chunk size 66232 perslab 15slab class 31: chunk size 82792 perslab 12slab class 32: chunk size 103496 perslab 10slab class 33: chunk size 129376 perslab 8slab class 34: chunk size 161720 perslab 6slab class 35: chunk size 202152 perslab 5slab class 36: chunk size 252696 perslab 4slab class 37: chunk size 315872 perslab 3slab class 38: chunk size 394840 perslab 2slab class 39: chunk size 493552 perslab 2slab class 40: chunk size 616944 perslab 1slab class 41: chunk size 771184 perslab 1slab class 42: chunk size 1048576 perslab 1<17 server listening (auto-negotiate)<18 server listening (auto-negotiate)<19 send buffer was 9216, now 7456540<19 server listening (udp)<23 send buffer was 9216, now 7456540<23 server listening (udp)<21 server listening (udp)<22 server listening (udp)<20 server listening (udp)<25 server listening (udp)<26 server listening (udp)<24 server listening (udp) |
附加功能:
1、 查看启动的memcached服务:
如果是linux系统,使用命令
1 |
neststat -anltp | grep 11211 |
如果是mac系统,使用命令:
1 |
lsof -i:11211 |
2、查看memcache的进程号(根据进程号,可以结束memcache服务:“kill -9 进程号”)
1 |
ps -ef | grep memcached |
安装Java-memcached-Client到maven repository
网上使用的客户端一般有两个
1、 java_memcached-release_2.6.6.jar
依赖的jar
A、commons-pool-1.5.6.jar
B、java_memcached-release_2.6.6.jar
C、slf4j-api-1.6.1.jar
D、slf4j-simple-1.6.1.jar
2、alisoft-xplatform-asf-cache-2.5.1-src.jar
这个东东是阿里软件的架构师岑文初进行封装的。里面的注释都是中文的,比较好。
依赖的jar
A、alisoft-xplatform-asf-cache-2.5.1.jar
B、commons-logging-1.0.4.jar
C、hessian-3.0.1.jar
D、log4j-1.2.9.jar
E、stax-api-1.0.1.jar
F、wstx-asl-2.0.2.jar
我们这里使用java_memcached-release_2.6.6.jar,我们可以去这个链接https://github.com/gwhalin/Memcached-Java-Client/downloads去下载最新的包,下下来之后我们要把它安装到maven repository中,以便我们以后在项目中使用。
因为java memcached client要依赖slf4j-simple、slf4j-api、commons-pool三个包,依此我们可以为其编辑一个pom文件,将java memcached client的jar包和pom文件一起安装,解决java memcached client对其他jar包的依赖。安装命令:
1 |
$ mvn install:install-file -Dfile=java_memcached-release_2.6.6.jar -DpomFile=java-memcached-2.6.6.pom |
pom文件为:
12345678910111213141516171819202122232425 |
<?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>com.danga</groupId> <artifactId>java-memcached</artifactId> <version>2.6.6</version> <dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.6.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.2</version> </dependency> <dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>1.5.6</version> </dependency> </dependencies> </project> |
Java-Client调用实例
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
package com.benjamin.utils.cache; import com.danga.MemCached.MemCachedClient;import com.danga.MemCached.SockIOPool; import java.util.Date; /** * Created by piqiu on 3/6/16. */public class MemcachedUtil { /** memcached客户端实例 **/ private static MemCachedClient cachedClient = new MemCachedClient(); /** * 初始化连接池 */ static { SockIOPool pool = SockIOPool.getInstance(); String[] servers = {"127.0.0.1:11211"}; Integer[] weights = {3}; // 设置服务器信息 pool.setServers(servers); pool.setWeights(weights); // 设置初始连接数 pool.setInitConn(10); pool.setMinConn(10); pool.setMaxConn(1000); pool.setMaxIdle(1000*60*60); //设置连接池守护线程的睡眠时间 pool.setMaintSleep(60); //设置TCP参数,连接超时 pool.setNagle(false); pool.setSocketTO(60); pool.setSocketConnectTO(0); //初始化并启动连接池 pool.initialize(); //压缩设置,超过指定大小的都压缩// cachedClient.setCompressEnable(true);// cachedClient.setCompressThreshold(64*1024); } private MemcachedUtil(){ } public static boolean add(String key, Object value) { return cachedClient.add(key, value); } public static boolean add(String key, Object value, Date expire) { return cachedClient.add(key, value, expire); } public static boolean put(String key, Object value) { return cachedClient.set(key, value); } public static boolean put(String key, Object value, Date expire) { return cachedClient.set(key, value, expire); } public static boolean replace(String key, Object value) { return cachedClient.replace(key, value); } public static boolean replace(String key, Object value, Date expire) { return cachedClient.replace(key, value, expire); } public static Object get(String key) { return cachedClient.get(key); }} |
12345678910111213141516171819202122232425 |
package com.benjamin.utils.cache; import org.junit.Test; import java.util.Date; /** * Created by piqiu on 3/6/16. */public class MemcachedTest { @Test public void testMemcached() throws InterruptedException { MemcachedUtil.put("hello", "worlds", new Date(3000)); // 过期时间还可以这么写new Date(System.currentTimeMillis()+3000) Thread.sleep(1000); String hello1 = (String)MemcachedUtil.get("hello"); System.out.println(hello1); Thread.sleep(1000); String hello2 = (String)MemcachedUtil.get("hello"); System.out.println(hello2); Thread.sleep(1000); String hello3 = (String)MemcachedUtil.get("hello"); System.out.println(hello3); }} |
执行结果
123 |
worldsworldsnull |
那么memcached里面的add和set方法有什么区别呢?
add:如果memcache服务器中已经存在要存储的key,此时add方法调用失败。
set:如果要设置的key不存在时,则set方法与add方法的效果一致;如果要设置的key已经存在时,则set方法与replace方法效果一样。
高级使用请参考:
http://snowolf.iteye.com/blog/1447348
API参考:
http://blog.csdn.net/qqiabc521/article/details/6438429