【翻译】Memcache 的使用
前几天接触到memcache的,这里学习下。希望看到这个文章的人能够纠错和补充。
http://sacharya.com/
前面写的是JBoss Cache和Memcached的比较。从而肯定了Memcached的简单,资源消耗小,便于维护的优点。
简介:
Memcached的优点:简单、独立、便于维护。
Memcached服务是一个内存缓存。它可以通过键值对存储包括字节、文档、原语等信息。想其他缓存一样,存储数据到内存中。从而当用户请求数据的时候,阻止用户区访问数据库、文件系统以及其他后端系统。这样就降低了后端系统的负载。提高了系统的扩展性。当数据存储到到内存后,访问数据时就会比昂贵的后天服务要快很多。
然而,Memcached并不是不变的存储空间。而且并不保证数据就一定会在缓存中,尽管你确实将数据存进去了。所以不要完全相信缓存。
Memcached的唯一一个限制就是cache的key的字符长度不能超过255个。并且被存储的值不能超过1MB。
安装:
1、安装Libevent:
Memcached使用Libevent库来处理网络IO。
$ cd libevent-1.4.11-stable$ autoconf$ ./configure --prefix=/usr/local$ make$ sudo make install?
2、安装Memcached:
从 Danga.com下载最新版本的Memcached。
$ cd memcached-1.4.0$ autoconf$ ./configure --prefix=/usr/local$ make$ sudo make install?
3、运行Memcached:
在11211端口启动512MB的守护线程,然后你就能通过端口远程登录到服务,使用一些操作命令。
$memcached -d -m 512 127.0.0.1 -p 1121$ telnet localhost 11211Trying ::1...Connected to localhost.Escape character is '^]'.get joeENDset joe 0 3600 10 (Note: TTL 3600 and 10 bytes)CaliforniaSTOREDget joeVALUE joe 0 10CaliforniaEND?
java Memcached 客户端:
可以在下面两个连接中下载客户端:http://code.google.com/p/spymemcached/? https://github.com/gwhalin/Memcached-Java-Client/wiki/ 这里使用了后者。连接中可以找到相应的API。
MemcachedClient c=new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211));c.set("someKey", 3600, someObject);Object myObject=c.get("someKey");c.delete("someKey")?
Memcached客户端是单线程的,set方法通过键值将值放到cache中。如果一个值已经在cache中存在就,原来的值就会被重写。set方法还设置了这个值的存活时间。
添加或者移除缓存服务:
如果你需要升级系统,给cache添加一个服务器。你只需要将新增加的服务器的ip和端口添加到现有的服务器中中的“池”里。memcached服务客户端,就会将它记录下来。相反如果你想去掉一个服务器,只需要将“池”中的ip和端口删除。这样会让数据命中失败一小段时间。这个数据不久就会恢复到其他服务器上面。如果你担心访问数据库,你可以在缓存服务器去掉后,将数据倒到其他服务器上面。
MemcachedClient c = new MemcachedClient(new BinaryConnectionFactory(),AddrUtil.getAddresses("server1:11211 server2:11211"));?
链接到“池”:
Memcached 建立的是TCP链接(Facebook 已经发布了一个Memcache的修改版本,使用的是UDP,去减少链接次数)来链接到Memcached服务。所以你想知道有多少服务链接被使用。
$ netstat -na | grep 11211tcp4 0 0 127.0.0.1.11211 127.0.0.1.59321 ESTABLISHEDtcp4 0 0 127.0.0.1.59321 127.0.0.1.11211 ESTABLISHED
?没有确切的方法去关闭链接,因为set和get方法都是动态的。我喜欢固定的链接,并且重用这些链接。这样可以防止建立TCP链接照成的开销。
Mycache单例:
这是我封装memcached的代码:
01.import net.spy.memcached.AddrUtil;02.import net.spy.memcached.BinaryConnectionFactory;03.import net.spy.memcached.MemcachedClient;04. 05.public class MyCache {06.private static final String NAMESPACE= "SACHARYA:5d41402abc4b2a76b9719d91101";07.private static MyCache instance = null;08.private static MemcachedClient[] m = null;09. 10.private MyCache() {11.try {12.m= new MemcachedClient[21];13.for (int i = 0; i <= 20; i ++) {14.MemcachedClient c = new MemcachedClient(15.new BinaryConnectionFactory(),16.AddrUtil.getAddresses("127.0.0.1:11211"));17.m[i] = c;18.}19.} catch (Exception e) {20. 21.}22.}23. 24.public static synchronized MyCache getInstance() {25.System.out.println("Instance: " + instance);26.if(instance == null) {27.System.out.println("Creating a new instance");28.instance = new MyCache();29.}30.return instance;31.}32. 33.public void set(String key, int ttl, final Object o) {34.getCache().set(NAMESPACE + key, ttl, o);35.}36. 37.public Object get(String key) {38.Object o = getCache().get(NAMESPACE + key);39.if(o == null) {40.System.out.println("Cache MISS for KEY: " + key);41.} else {42.System.out.println("Cache HIT for KEY: " + key);43.}44.return o;45.}46. 47.public Object delete(String key) {48.return getCache().delete(NAMESPACE + key);49.}50. 51.public MemcachedClient getCache() {52.MemcachedClient c= null;53.try {54.int i = (int) (Math.random()* 20);55.c = m[i];56.} catch(Exception e) {57. 58.}59.return c;60.}61.}?
在上面的代码:
1、 我使用了BinaryConnectionFactory,这个一个新功能,它使用了新的字节流协议。使解析文本更加有效。
2、MyCache是一个单例,但它被实例化的时候会建立21个链接。
3、我的key的格式是:SACHARYA:5d41402abc4b2a76b9719d91101:key。SACHARYA是我们域。这样我就可以使用相同的cache服务存储我的不同应用的数据。第二个随即字符串是为了隐藏key。最后就产生了数据的唯一标识。
简单使用:
通常情况下,你可以在系统瓶颈处使用cache。
01.public List<Product> getAllProducts() {02.List<Product> products = (List<Product>) MyCache.getInstance().get("AllProducts");03.if(products != null) {04.return products;05.}06.products = getAllProductsFromDB()07.if(products) {08.MyCache.getInstance().put("AllProducts", 3600, customer);09.}10.return products;11.}12. 13.public void updateProduct(String id) {14.updateProductIntoDB(id)15.MyCache.getInstance().delete("AllProducts");16.}17.public void deleteProduct(String id) {18.deleteProductFromDB(id)19.MyCache.getInstance().delete("AllProducts");?
缓存警告:
当应用第一次启动的时候,cache中没有数据。所以你可以通过一个调度程序预热cache。防止开始时大量访问端点(如数据库)。
监控cache效率:
stats命令提供了重要的信息,这些信息可以告诉你cache的执行情况。它显示了所有的get请求,以及多少命中成功,多少命中失败。
$ telnet localhost 11211statsSTAT cmd_get 13219STAT get_hits 12232STAT get_misses 512
?以上显示的意思是总共有13219个请求,其中有12232请求得到了想要的数据(命中)。有512个请求没有得到想要的数据。