Memcached是一种高性能的分布式内存对象缓存系统(memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能,其“分布式”由客户端函数库完成,成熟算法的为一致性Hash),用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。很多大型网站都使用了Memcached做缓存。MemCache依赖于libevent,后者是一个基于事件触发的网络库。
下面介绍Linux下MemCache数据库的安装和使用。
libevent版本:libevent-2.0.22-stable.tar.gz
MemCache版本:memcached-1.4.29.tar.gz
1、安装libevent
//make install后会在==prefix指定的地方产生 bin、include、lib 文件夹
[root@localhost src]# tar -zxvf libevent-2.0.22-stable.tar.gz [root@localhost src]# cd libevent-2.0.22-stable [root@localhost libevent-2.0.22-stable]# ./configure --prefix=/usr/local/libevent [root@localhost libevent-2.0.22-stable]# make [root@localhost libevent-2.0.22-stable]# make install
2、安装Memcached服务端
//make install后会在==prefix指定的地方产生 bin、include、share 文件夹
[root@localhost src]# tar -zxvf memcached-1.4.29.tar.gz [root@localhost src]# cd memcached-1.4.29 [root@localhost memcached-1.4.29]# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent [root@localhost memcached-1.4.29]# make [root@localhost memcached-1.4.29]# make install
3、启动
[root@localhost /] /usr/local/memcached/bin/memcached -d -m 256 -u root -p 11211 -c 1024 -P /tmp/memcached.pid
选项说明:(更多参考 简单之美的博客 )
-d:选项是启动一个守护进程, -m:是分配给Memcache使用的内存数量,单位是MB,默认是64 MB. -M:内存耗尽时返回错误而并非删除条目. -u:是运行Memcache的用户. -l:是监听的服务器IP地址,我这里没有填. -p:是设置Memcache tcp监听的端口,默认是11211. -c:选项是最大运行的并发连接数,默认是1024,按照你服务器的负载量来设定. -P:是设置保存Memcache的pid文件. -vv:打印客户端的请求和返回信息. -i:打印memcached和libevent的版权信息 -h:查看选项说明
运行 telnet localhost 11211 能连上则说明启动成功
4、命令行操作
4.1 基本常用操作
(更多可参考:简单之美的博客、MemCache常用命令及使用说明)
先:telnet localhost 11211 写:set time 2016 读:get time 查看状态:stats pid Memcached 进程ID uptime Memcached 运行时间,单位:秒 time Memcached 当前的UNIX时间 version Memcached 的版本号 rusage_user 该进程累计的用户时间,单位:秒 rusage_system 该进程累计的系统时间,单位:秒 curr_items Memcached 当前存储的内容数量 total_items Memcached 启动以来存储过的内容总数 bytes Memcached 当前存储内容所占用的字节数(*/1024/1024=mb) curr_connections 当前连接数量 total_connections Memcached 运行以来接受的连接总数 connection_structures Memcached 分配的连接结构的数量 cmd_get 查询请求总数 cmd_set 存储(添加/更新)请求总数 ... get_hits 查询成功获取数据的总次数 get_misses 查询成功未获取到数据的总次数 bytes_read Memcached 从网络读取到的总字节数 bytes_written Memcached 向网络发送的总字节数 limit_maxbytes Memcached 在存储时被允许使用的字节总数 退出telnet:quit
4.2 列出所有key
4.2.1 方法
先用 stats items 得到所有item的id;再用 stats cachedump item_id 0 得到item的key;最后可以根据key得到value。示例如下:(参考资料:http://www.darkcoding.net/software/memcached-list-all-keys/)
stats items STAT items:1:number 3 //The first number after ‘items’ is the slab id. the value after 'number' is the pairs of K/V in the slab. ...... STAT items:23:crawler_items_checked 0 STAT items:23:lrutail_reflocked 0 END stats cachedump 23 0 //Request a cache dump for each slab id, with a limit for the max number of keys to dump. dump all key in the corresponding slab when it's 0 ITEM beijing_car_distribution [11215 b; 0 s] END get beijing_car_distribution VALUE beijing_car_distribution 0 11215 [{"region":"881,1731","count":6},{"region":"874,1730","count":29} ......"count":5}] END
4.2.2 命令
host=192.168.6.135 port=11211 num=`echo 'stats items' |nc $host $port |grep number |tail -n1 | grep -o ":[0-9]+" |grep -o "[0-9]+" ` for ((i=1;i<=$num;i++)) do echo echo echo 'slab '$i echo 'stats cachedump '$i' 0' | nc $host $port done
4.2.3 其他组合命令
得到 items:id:number xx 列表: echo 'stats items' |nc 192.168.6.135 11211 |grep number
得到某个itemid的所有K/V pair: echo stats cachedump 22 0 | nc 192.168.6.135 11211
4.3 各命令行具体用法
5、代码操作
通过代码操作MemCache,常用的Java客户端有:spymemcached客户端(Java)、XMemcached客户端(Java)、Nodejs等。(具体可参考:简单之美的博客)
以XMemcached为例:
1 /** 2 * 3 */ 4 package cn.edu.buaa.act.test.TestMemcache; 5 6 import java.text.SimpleDateFormat; 7 import java.util.ArrayList; 8 import java.util.HashMap; 9 import java.util.Map; 10 11 import net.rubyeye.xmemcached.MemcachedClient; 12 import net.rubyeye.xmemcached.MemcachedClientBuilder; 13 import net.rubyeye.xmemcached.XMemcachedClientBuilder; 14 import net.rubyeye.xmemcached.command.BinaryCommandFactory; 15 import net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator; 16 import net.rubyeye.xmemcached.utils.AddrUtil; 17 18 /** 19 * @author zsm 20 * 21 */ 22 public class MemcacheTest { 23 private final int bucket = 1000; 24 private MemcachedClient mcClient1; 25 private MemcachedClient mcClient2; 26 27 public MemcacheTest(String memAddr1, String memAddr2) { 28 try { 29 30 MemcachedClientBuilder mcbuilder = new XMemcachedClientBuilder(AddrUtil.getAddresses(memAddr1)); 31 mcbuilder.setSessionLocator(new KetamaMemcachedSessionLocator()); 32 mcbuilder.setCommandFactory(new BinaryCommandFactory()); 33 mcbuilder.setConnectionPoolSize(1); 34 mcbuilder.setFailureMode(false); 35 mcClient1 = mcbuilder.build(); 36 37 mcbuilder = new XMemcachedClientBuilder(AddrUtil.getAddresses(memAddr2)); 38 mcbuilder.setSessionLocator(new KetamaMemcachedSessionLocator()); 39 mcbuilder.setCommandFactory(new BinaryCommandFactory()); 40 mcbuilder.setConnectionPoolSize(1); 41 mcbuilder.setFailureMode(false); 42 mcClient2 = mcbuilder.build(); 43 44 System.out.printf(Thread.currentThread().getName() + "||: mcClient1 create instance: %s %s %s ", 45 this.getClass().hashCode(), memAddr1, memAddr2); 46 } catch (Exception e) { 47 e.printStackTrace(); 48 } 49 } 50 51 public void Set(String key, String value) { 52 try { 53 mcClient1.set(key, 0, value); 54 } catch (Exception e) { 55 // TODO Auto-generated catch block 56 e.printStackTrace(); 57 } 58 try { 59 mcClient2.set(key, 0, value); 60 } catch (Exception e) { 61 // TODO Auto-generated catch block 62 e.printStackTrace(); 63 } 64 } 65 66 private String Get(String key) { 67 try { 68 return mcClient1.get(key); 69 } catch (Exception e) { 70 // TODO Auto-generated catch block 71 e.printStackTrace(); 72 } 73 try { 74 return mcClient2.get(key); 75 } catch (Exception e) { 76 // TODO Auto-generated catch block 77 e.printStackTrace(); 78 } 79 return null; 80 } 81 82 private Map<String, Object> Get(ArrayList<String> keys) { 83 try { 84 Map<String, Object> res = new HashMap<String, Object>(); 85 Map<String, Object> tmp = null; 86 int keysLen = keys.size(); 87 if (keysLen > bucket) { 88 ArrayList<String> keyPart = new ArrayList<String>(); 89 for (int i = 0; i < keysLen; i++) { 90 keyPart.add(keys.get(i)); 91 if (keyPart.size() == bucket || i == keysLen) {// 分批请求 92 if ((tmp = mcClient1.get(keyPart)) == null) {// 请求 93 tmp = mcClient2.get(keyPart); 94 } 95 res.putAll(tmp); 96 keyPart.clear(); 97 } 98 } 99 } else { 100 if ((res = mcClient1.get(keys)) == null) { 101 res = mcClient2.get(keys); 102 } 103 } 104 return res.size() > 0 ? res : null; 105 } catch (Throwable e) { 106 System.out.println(e.getMessage()); 107 return null; 108 } 109 } 110 111 public static void main(String[] args) { 112 // TODO Auto-generated method stub 113 MemcacheTest mt = new MemcacheTest("192.168.6.135:11211", "192.168.6.136:11211"); 114 mt.Set("zsmtime", new SimpleDateFormat("yyyyMMdd_hhMMssSS").format(System.currentTimeMillis())); 115 System.out.println(mt.Get("967790142906obd")); 116 117 } 118 }
相关Maven依赖:
<dependency> <groupId>com.googlecode.xmemcached</groupId> <artifactId>xmemcached</artifactId> <version>2.0.0</version> </dependency>