首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 互联网 >

【通译】Memcache 的使用

2012-07-01 
【翻译】Memcache 的使用前几天接触到memcache的,这里学习下。希望看到这个文章的人能够纠错和补充。http://sa

【翻译】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个请求没有得到想要的数据。

热点排行