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的童鞋可以使用
这个命令来安装
没有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包的根目录,并执行以下命令:
1 2
|
$ sudo ./configure --prefix=/usr/local/libevent-2.0.22 $ sudo make
|
make的最后会提示一个错误,这个错误是因为缺少openssl
1 2 3 4 5 6 7
|
bufferevent_openssl.c:60:10: fatal error: 'openssl/bio.h' file not found
^ 1 error generated. make[2]: *** [bufferevent_openssl.lo] Error 1 make[1]: *** [all-recursive] Error 1 make: *** [all] Error 2
|
这时候我们继续执行命令:
1 2 3 4
|
(下面是软连接,前面的一个路径是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的软件包的根目录,执行以下命令:
1 2 3 4
|
(一定要加上--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
|
下面是每个参数的说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
-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 显示帮助
|
附上一个启动后的效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
[piqiu@localhost /usr/local/memcached-1.4.25/bin]$./memcached -p 11211 -m 64 -u root -vv slab class 1: chunk size 96 perslab 10922 slab class 2: chunk size 120 perslab 8738 slab class 3: chunk size 152 perslab 6898 slab class 4: chunk size 192 perslab 5461 slab class 5: chunk size 240 perslab 4369 slab class 6: chunk size 304 perslab 3449 slab class 7: chunk size 384 perslab 2730 slab class 8: chunk size 480 perslab 2184 slab class 9: chunk size 600 perslab 1747 slab class 10: chunk size 752 perslab 1394 slab class 11: chunk size 944 perslab 1110 slab class 12: chunk size 1184 perslab 885 slab class 13: chunk size 1480 perslab 708 slab class 14: chunk size 1856 perslab 564 slab class 15: chunk size 2320 perslab 451 slab class 16: chunk size 2904 perslab 361 slab class 17: chunk size 3632 perslab 288 slab class 18: chunk size 4544 perslab 230 slab class 19: chunk size 5680 perslab 184 slab class 20: chunk size 7104 perslab 147 slab class 21: chunk size 8880 perslab 118 slab class 22: chunk size 11104 perslab 94 slab class 23: chunk size 13880 perslab 75 slab class 24: chunk size 17352 perslab 60 slab class 25: chunk size 21696 perslab 48 slab class 26: chunk size 27120 perslab 38 slab class 27: chunk size 33904 perslab 30 slab class 28: chunk size 42384 perslab 24 slab class 29: chunk size 52984 perslab 19 slab class 30: chunk size 66232 perslab 15 slab class 31: chunk size 82792 perslab 12 slab class 32: chunk size 103496 perslab 10 slab class 33: chunk size 129376 perslab 8 slab class 34: chunk size 161720 perslab 6 slab class 35: chunk size 202152 perslab 5 slab class 36: chunk size 252696 perslab 4 slab class 37: chunk size 315872 perslab 3 slab class 38: chunk size 394840 perslab 2 slab class 39: chunk size 493552 perslab 2 slab class 40: chunk size 616944 perslab 1 slab class 41: chunk size 771184 perslab 1 slab 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系统,使用命令:
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文件为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
<?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调用实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
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 {
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);
pool.setNagle(false); pool.setSocketTO(60); pool.setSocketConnectTO(0);
pool.initialize();
}
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); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
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)); 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); } }
|
执行结果
那么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