Memcached服务器安装、配置、使用详解

Memcached服务器安装、配置、使用详解

  原文  
http://shiyanjun.cn/archives/873.html

我使用的是CentOS 6.4系统,安装的Memcached版本为1.4.20。这里,记录一下安装配置的过程,以及如何使用一些常用的客户端来访问Memcached存储的数据。

安装配置

首先,编译、安装、配置libevent库,执行如下命令:

wget https://github.com/downloads/libevent/libevent/libevent-1.4.14b-stable.tar.gz tar xvzf libevent-1.4.14b-stable.tar.gz ln -s /usr/local/libevent-1.4.14b-stable /usr/local/libevent cd /usr/local/libevent ./configure make make install

然后,编译、安装、配置Memcached,执行如下命令行:

wget http://www.memcached.org/files/memcached-1.4.20.tar.gz tar xvzf memcached-1.4.20.tar.gz ln -s /usr/local/memcached-1.4.20 /usr/local/memcached ./configure --with-libevent=/usr/local/libevent/ make make install

如果没有出错,安装成功。

管理memcached服务

  • 启动Memcached

一般情况下,简单地可以使用类似如下形式,启动Memcached服务:

/usr/local/bin/memcached -d -m 64 -I 20m -u root -l 192.168.4.86 -p 11211 -c 1024 -P /usr/local/memcached/memcached.pid

上述命令行中,基于上面各个选项,以及其他一些选项的含义,说明如下表所示:

选项含义说明
-d指定memcached进程作为一个守护进程启动
-m <num>指定分配给memcached使用的内存,单位是MB
-u <username>运行memcached的用户
-l <ip_addr>监听的服务器IP地址,如果有多个地址的话,使用逗号分隔,格式可以为“IP地址:端口号”,例如:-l 指定192.168.0.184:19830,192.168.0.195:13542;端口号也可以通过-p选项指定
-p <num>Memcached监听的端口,要保证该端口号未被占用
-c <num>设置最大运行的并发连接数,默认是1024
-R <num>为避免客户端饿死(starvation),对连续达到的客户端请求数设置一个限额,如果超过该设置,会选择另一个连接来处理请求,默认为20
-k设置锁定所有分页的内存,对于大缓存应用场景,谨慎使用该选项
-P保存memcached进程的pid文件
-s <file>指定Memcached用于监听的UNIX socket文件
-a <perms>设置-s选项指定的UNIX socket文件的权限
-U <num>指定监听UDP的端口,默认11211,0表示关闭
-M当内存使用超出配置值时,禁止自动清除缓存中的数据项,此时Memcached不可以,直到内存被释放
-r设置产生core文件大小
-f <factor>用于计算缓存数据项的内存块大小的乘数因子,默认是1.25
-n为缓存数据项的key、value、flag设置最小分配字节数,默认是48
-C禁用CAS
-h显示Memcached版本和摘要信息
-v输出警告和错误信息
-vv打印信息比-v更详细:不仅输出警告和错误信息,也输出客户端请求和响应信息
-i打印libevent和Memcached的licenses信息
-t <threads>指定用来处理请求的线程数,默认为4
-D <char>用于统计报告中Key前缀和ID之间的分隔符,默认是冒号“:”
-L尝试使用大内存分页(pages)
-B <proto>指定使用的协议,默认行为是自动协商(autonegotiate),可能使用的选项有auto、ascii、binary。
-I <size>覆盖默认的STAB页大小,默认是1M
-F禁用flush_all命令
-o <options>指定逗号分隔的选项,一般用于用于扩展或实验性质的选项
  • 停止Memcached

可以通过Linux的如下命令查询到Memcached的进程号:

ps -ef | grep memcached

然后杀掉Memcached服务进程:

kill -9 <PID>

-9表示强制杀掉进程。

Memcached启动以后,可以通过客户端来操作缓存中的数据,我们说明一些常用的客户端,及其使用方法。

Telnet客户端

Telnet客户端可以通过命令行的方式来监控查看Memcached服务器存储数据的情况。例如,Memcached的服务地址为192.168.4.86:11211,可以telnet到该服务端口:

telnet 192.168.4.86 11211

如果连接成功,可以使用如下一些命令:

  • stats命令

该命令用于显示服务器信息、统计数据等,结果示例数据(来自www.2cto.com网站),例如:

STAT pid 22362    //memcache服务器的进程ID www.2cto.com STAT uptime 1469315 //服务器已经运行的秒数 STAT time 1339671194 //服务器当前的unix时间戳 STAT version 1.4.9 //memcache版本 STAT libevent 1.4.9-stable //libevent版本 STAT pointer_size 64 //当前操作系统的指针大小(32位系统一般是32bit,64就是64位操作系统) STAT rusage_user 3695.485200 //进程的累计用户时间 STAT rusage_system 14751.273465 //进程的累计系统时间 STAT curr_connections 69 //服务器当前存储的items数量 STAT total_connections 855430 //从服务器启动以后存储的items总数量 STAT connection_structures 74 //服务器分配的连接构造数 STAT reserved_fds 20 // STAT cmd_get 328806688 //get命令(获取)总请求次数 STAT cmd_set 75441133 //set命令(保存)总请求次数 www.2cto.com STAT cmd_flush 34 //flush命令请求次数 STAT cmd_touch 0 //touch命令请求次数 STAT get_hits 253547177 //总命中次数 STAT get_misses 75259511 //总未命中次数 STAT delete_misses 4 //delete命令未命中次数 STAT delete_hits 565730 //delete命令命中次数 STAT incr_misses 0 //incr命令未命中次数 STAT incr_hits 0 //incr命令命中次数 STAT decr_misses 0 //decr命令未命中次数 STAT decr_hits 0 //decr命令命中次数 STAT cas_misses 0 //cas命令未命中次数 STAT cas_hits 0 //cas命令命中次数 STAT cas_badval 0 //使用擦拭次数 STAT touch_hits 0 //touch命令未命中次数 STAT touch_misses 0 //touch命令命中次数 STAT auth_cmds 0 //认证命令处理的次数 STAT auth_errors 0 //认证失败数目 STAT bytes_read 545701515844 //总读取字节数(请求字节数) STAT bytes_written 1649639749866 //总发送字节数(结果字节数) STAT limit_maxbytes 2147483648 //分配给memcache的内存大小(字节) STAT accepting_conns 1 //服务器是否达到过最大连接(0/1) STAT listen_disabled_num 0 //失效的监听数 STAT threads 4 //当前线程数 STAT conn_yields 14 //连接操作主动放弃数目 STAT hash_power_level 16 // STAT hash_bytes 524288 STAT hash_is_expanding 0 STAT expired_unfetched 30705763 STAT evicted_unfetched 0 STAT bytes 61380700 //当前存储占用的字节数 STAT curr_items 28786 //当前存储的数据总数 STAT total_items 75441133 //启动以来存储的数据总数 STAT evictions 0 //为获取空闲内存而删除的items数(分配给memcache的空间用满后需要删除旧的items来得到空间分配给新的items) STAT reclaimed 39957976 //已过期的数据条目来存储新数据的数目 END

上面给出了各个统计项的含义说明,不再累述。 stats命令有几个二级子项,说明如下表所示:

命令含义说明
stats slabs显示各个slab的信息,包括chunk的大小、数目、使用情况等
stats items显示各个slab中item的数目和最老item的年龄(最后一次访问距离现在的秒数)
stats detail [on|off|dump]设置或者显示详细操作记录; 
参数为on,打开详细操作记录; 
参数为off,关闭详细操作记录; 
参数为dump,显示详细操作记录(每一个键值get、set、hit、del的次数)
stats malloc打印内存分配信息
stats sizes打印缓存使用信息
stats reset重置统计信息
  • get命令

用于获取缓存的数据,键为key。 用法格式:

get <key>*\r\n

示例如下所示:

get basis_behavior_user

结果示例,如下所示:

VALUE basis_behavior_user 0 451{"aaData":[["d1a2233dc382432b8e19e40254fdb98a","100000002223484","1402563046319","c4f82195815300bcf39a5232707ad9c1","1","0","EBEST_W70","4.0.4","2.2.2.","wifi","","EBEST","19","854*480","H-yun35","00:08:22:da:c1:ce","863531010517866","c4f82195815300bcf39a5232707ad9c11402562805664","460010255508963","1901589461","1402563045960","429","338","23197","1","0","0","2014-06-12_16:50:46","-1","0","3"]],"sEcho":1,"iTotalRecords":0,"iTotalDisplayRecords":0} END

也可以get多个key对应的值,如下所示:

get name hobby
VALUE name 1 7 1234567 VALUE hobby 0 25 tenis basketball football END
  • set命令

用法格式:

set <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n

示例:

set name 0 1800 7 shirdrn STORED get name VALUE name 0 7 shirdrn END
  • delete命令

给定键key,删除缓存中key对应的数据。

  • add命令

用法格式:

add <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n

示例:

add hobby 0 1800 10 basketball STORED get hobby VALUE hobby 0 10 basketball END
  • replace命令

覆盖一个已经存在Key及其对应的Value,替换一定要保证替换后的值的长度原始长度相同,否则replace失败。 用法格式:

replace <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n

示例:

get name
VALUE name 0 7
shirdrn
END
replace name 0 1800 7 youak47 STORED get name VALUE name 0 7 youak47 END
  • append命令

在一个已经存在的数据值(value)上追加,是在数据值的后面追加。 用法格式:

append <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n

示例:

get hobby
VALUE hobby 0 10
basketball
END
append hobby 0 1800 9 football STORED get hobby VALUE hobby 0 19 basketball football END
  • prepend命令

在一个已经存在的数据值(value)上追加,是在数据值的前面追加。 用法格式:

prepend <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n

示例:

get hobby
VALUE hobby 0 19
basketball football
END
prepend hobby 0 1800 6 tenis STORED get hobby VALUE hobby 0 25 tenis basketball football END
  • incr命令

计数命令,可以在原来已经存在的数字上进行累加求和,计算并存储新的数值。 用法格式:

incr <key> <value> [noreply]\r\n

示例:

set active_users 0 1000000 7 1000000 STORED get active_users VALUE active_users 0 7 1000000 END incr active_users 99 1000099
  • decr命令

计数命令,可以在原来已经存在的数字上进行减法计算,计算并存储新的数值。 用法格式:

decr <key> <value> [noreply]\r\n

示例:

get active_users
VALUE active_users 0 7 1000099 END decr active_users 3456 996643
  • flush_all命令

使缓存中的数据项失效,可选参数是在多少秒后失效。 用法格式:

flush_all [<time>] [noreply]\r\n
  • version命令

返回Memcached服务器的版本信息。

  • quit命令

退出telnet终端。

Java客户端

可以使用Java语言编写代码来访问Memcached缓存。目前,可以使用的Java客户端很多,这里简单介绍几个。

  • spymemcached客户端

示例代码,如下所示:

package org.shirdrn.spymemcached;

import net.spy.memcached.AddrUtil;
import net.spy.memcached.BinaryConnectionFactory; import net.spy.memcached.MemcachedClient; import net.spy.memcached.internal.OperationFuture; public class TestSpymemcached { public static void main(String[] args) throws Exception { String address = "192.168.4.86:11211"; MemcachedClient client = new MemcachedClient(new BinaryConnectionFactory(), AddrUtil.getAddresses(address)); String key = "magic_words"; int exp = 3600; String o = "hello"; // set OperationFuture<Boolean> setFuture = client.set(key, exp, o); if(setFuture.get()) { // get System.out.println(client.get(key)); // append client.append(key, " the world!"); System.out.println(client.get(key)); // prepend client.prepend(key, "Stone, "); System.out.println(client.get(key)); // replace o = "This is a test for spymemcached."; OperationFuture<Boolean> replaceFuture = client.replace(key, exp, o); if(replaceFuture.get()) { System.out.println(client.get(key)); // delete client.delete(key); System.out.println(client.get(key)); } } client.shutdown(); } }

更多用法,可以参考后面的链接。

  • XMemcached客户端

示例代码,如下所示:

package org.shirdrn.xmemcached;

import java.io.File; import java.io.IOException; import java.io.Serializable; import java.net.InetSocketAddress; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicLong; import net.rubyeye.xmemcached.CASOperation; import net.rubyeye.xmemcached.GetsResponse; import net.rubyeye.xmemcached.MemcachedClient; import net.rubyeye.xmemcached.XMemcachedClientBuilder; import net.rubyeye.xmemcached.command.BinaryCommandFactory; import net.rubyeye.xmemcached.exception.MemcachedException; import net.rubyeye.xmemcached.utils.AddrUtil; public class UsingXMemcachedClient { public static void main(String[] args) throws IOException { String servers = "192.168.4.86:11211"; // build and create a client XMemcachedClientBuilder builder = new XMemcachedClientBuilder( AddrUtil.getAddresses(servers)); builder.setCommandFactory(new BinaryCommandFactory()); final MemcachedClient client = builder.build(); // examples using client to operate final String key = "ghost"; try { // add client.add(key, 0, "Ghost wind blows!"); System.out.println("add & get: " + client.get(key)); // append client.append(key, " It's a lie."); System.out.println("append & get: " + client.get(key)); // prepend client.prepend(key, "Who's said?! "); System.out.println("prepend & get: " + client.get(key)); // replace client.replace(key, 0, "Everything is nothing!"); System.out.println("replace & get: " + client.get(key)); // delete client.delete(key); System.out.println("delete & get: " + client.get(key)); // gets List<String> keys = Arrays.asList(new String[] { "key1", "key2", "key3" }); for(String k : keys) { client.set(k, 3600, "v:" + System.nanoTime()); } Map<String, GetsResponse<Object>> values = client.gets(keys); for(Map.Entry<String, GetsResponse<Object>> entry : values.entrySet()) { System.out.println("key=" + entry.getKey() + ", value=" + entry.getValue().getValue()); } // cas final AtomicLong seq = new AtomicLong(System.nanoTime()); ExecutorService pool = Executors.newCachedThreadPool(); for(int i=0; i<10; i++) { pool.execute(new Runnable() { @Override public void run() { while(true) { CacheResult o = new CacheResult(); o.file = new File("/opt/status/servers.lst"); o.lastmodified = seq.incrementAndGet(); System.out.println("#" + Thread.currentThread().getId() + "=>o: " + o); try { client.set(key, 0, o); Thread.sleep(100); } catch (TimeoutException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MemcachedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }); } Thread.sleep(3000); for(int i=0; i<10; i++) { client.cas(key, new CASOperation<CacheResult>() { @Override public int getMaxTries() { return 3; } @Override public CacheResult getNewValue(long arg0, CacheResult result) { CacheResult old = result; CacheResult nu = new CacheResult(); nu.file = old.file; nu.lastmodified = seq.incrementAndGet(); System.out.println("cas: old=" + old + ", new=" + nu); return result; } }); } pool.shutdown(); // flush_all client.flushAll(); // stats List<InetSocketAddress> addresses = AddrUtil.getAddresses(servers); for(InetSocketAddress addr : addresses) { Map<String, String> stats = client.stats(addr); System.out.println(stats); } } catch (TimeoutException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (MemcachedException e) { e.printStackTrace(); } synchronized(client) { try { client.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } static class CacheResult implements Serializable { private static final long serialVersionUID = 3349686173080590047L; private File file; private long lastmodified; @Override public String toString() { return "file=[" + file + ", lastmodified=" + lastmodified + "]"; } } }

 

    原文作者:memcached
    原文地址: https://www.cnblogs.com/atwanli/articles/7093832.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞