memcache

Memcache



目录

Memcache 1

一、Memcache介绍 1

1.What is Memcache? 1

2.Memcache作用? 1

3.互联网常见缓存软件: 1

4.Memcached在企业工作中的应用场景 1

5.Memcached服务的软件特点 2

6.Memcached工作原理 3

7.Memcached工作原理深入(内存管理机制) 4

Memcached内存管理机制缺点及优化策略 4

二、Memcache部署 4

1.安装memcached 5

2.Memcached状态查看 6

3.关闭memcached,测试数据是否丢失 9

4.Memcached服务管理命令 9

三、监控Memcached 10

1.memcache.php 10

2.check_tcp 10

3.Nagios check_memcached插件 12





一、Memcache介绍

1.What is Memcache?

Memcache是一款开源的、高性能的纯内存缓存服务软件,Memcache项目诞生于2003年。Mem就是内存的意思,cache是缓存的意思,d是daemon的意思。Memcache服务分为服务端和客户端两部分,C/S模式。

服务端软件:memcached-1.4.13

客户端软件:memcache-2.25

Memcache官方网站:http://memcache.org


2.Memcache作用?

在启动Memcached时,会指定一个内存大小参数,然后会被分配一个内存空间。当我们读取数据库后的业务数据,放入Memcached缓存中,下一次请求同样数据的用户,直接去Memcachd取数据返回给用户。

这样做的好处?

(1)对于用户来说,用户访问网站更快了,体验更好了。

(2)数据库压力降低了,内存没有的时候,就会请求数据库。

(3)提升网站并发访问,服务器数量变少。


3.互联网常见缓存软件:

Memcached 纯内存 用来缓存后端数据库的数据(用户信息,帖子,博文等)

Memcachedb 内存+磁盘 新浪开发,Memcacehd+BDB 缓存后端数据库数据,直接做数据库用

Redis 内存+磁盘 作用同Memcachedb 主从复制,数据类型更丰富。

squid 内存+磁盘

varinish 内存

缓存静态图片,JS,CSS,HTML,视频等。CDN就是利用这类软件做的分布式缓存。


4.Memcached在企业工作中的应用场景

1|作为数据库的前端缓存应用

(1)完整缓存(易)

例如:京东的商品分类,就可以事先放到Memcached内存里,然后在对外提供数据访问。这个被称之为预热。 

此时可以只读取缓存就能读到商品分类数据,无需读取数据库,所以数据库的压力就降下来了。


(2)热点缓存(难)

热点缓存一般是指用户更新的商品,例如淘宝的卖家,当卖新增商品后,淘宝网的程序就会把商品写入数据库,然后读取写入的数据,把这部分数据,放入Memcached内存中,下一次访问这个商品的请求直接从Memcached内存中取走了。这种方法用来缓存网站热点的数据,即Memcached中缓存经常被访问的数据。

这个过程可以通过程序实现,也可以在数据库上安装Memcache插件,直接由数据库触发更新内容到Memcached中。


 2|Memcached作为集群后端的session会话保持

web集群session共享存储设置:

默认php.ini中session的类型和配置路径:

#session.save_handler = files

#session.save_path = "/tmp"

修改成如下配置:

session.save_handler = memcache

session.save_path = "tcp://10.0.0.18:11211"


3|Memcached分布式缓存

[分布式应用1]

Memcache支持分布式,我们在应用服务器上改造,就可以更好的支持。

例如:可以根据key适当进行有规律的,比如以用户为主的网站来说,每个用户都有UserID,那么可以根据ID来进行提取和存取,比如1开头的用户保存在第一台Memcache服务器上,以2开头的保存在第二台Memcache服务器上,存取数据都先按照UserID来进行转换和存取。

[分布式应用2]

在应用服务器上通过程序及URL_HASH,一致性哈希算法去访问Memcached服务

[分布式应用3]

门户网站,例如百度,会通过一个中间件代理(透明)负责请求后端的Cache服务。 

[分布式应用4]

可以用常见的LVS,haproxy做Cache的负载均衡,和普通web应用服务相比,这里的重点是调度算法,Cache一般会选择URL_HASH及一致性hash算法。


分布式缓存集群:

(1)所有MC服务器内存的内容都是不一样的。这些服务器内容加起来接近数据库的容量

(2)通过在客户端程序或者MC的负载均衡器上用HASH算法,让同一内容都分配到一个MC服务器

(3)普通的HASH算法对于节点宕机会带来大量的数据流动(失效),可能会引起雪崩效应

(4)一致性HASH算法可以让节点宕机对节点的数据流动(失效)降到最低



5.Memcached服务的软件特点

C/S模式架构

Memcached是一套C/S模式架构的软件,由C语言编写,总共2000多行代码。

协议简单

使用基于文本行的协议,能通过telnet/nc直接操作Memcached服务存取数据。

异步I/O 模型,使用libevent作为事件处理通知机制。

libevent是一套利用C开发的程序库,它将BSD系统的kqueue,Linux系统的epoll等事件处理功能封装成一个接口,确保即使服务器端的连接数增加也能发挥很好的性能。

key/value键值数据类型

被缓存的数据以key/value键值形式存在

纯内存存取管理模式

Memcached有一套自己管理内存的方式,这套管理方式非常高效,即全部数据都存放于Memcached服务事先分配的内存中,无持久性存储的设计,和系统内存一样,重启系统或Memcached服务,Memcached内存中的数据库丢失。

当内存中缓存的数据容量达到启动时设定的内存值时,就自动使用LRU算法删除过期的缓存数据。也可以对存储的数据设置过期时间,这样过期后数据自动被清除,服务本身不会监控过期,而是在访问的时候查看key的时间戳判断是否过期。

  如果希望重启后,数据依然保留,那么就需要类似sina开发的memcacehdb,redis等持久化内存缓存系统。

多个Memcached集群节点互不通信

各个Memcached服务器之间互相不通信,都是独立的存取数据,不共享任何信息,并且数据内容应该是不一致的。通过对客户端的设计,让Memcached具有分布式,能支持海量缓存和大规模应用。

淘宝的Tengine支持了一致性HASH模块

http://tengine.taobao.org/document_cn/http_upstream_consistent_hash_cn.html



6.Memcached工作原理

   Memcached是一套C/S模式架构的软件,在服务端启动服务守护进程可以为memcached服务器指定监听的IP地址、端口号、并发访问连接数以及分配多少内存来处理客户端的请求参数。

    Memcached由C语言开发, 全部代码2000多行,采用异步I/O模式,其实现方式是基于libevent事件的单进程、单线程的。使用libevent作为事件通知机制,多个服务器端可以协同工作,但这些服务器端之间是没有任何通信联系的,每个服务器端只对自己的数据进行管理。应用程序端通过制定缓存服务器的IP地址和端口,就可以连接memcacehd服务互相通信。

    需要被缓存的数据以key/value键值对的形式保存在服务器端预分配的内存区中,每个被缓存的数据都有唯一的标识key,操作Memcached中的数据通过这个唯一标识key进行。缓存到Memcached中的数据仅放置在Memcached服务预分的内存中,而非存储在Memcached所在的磁盘上,因此存取速度非常快。

    由于Memcached服务自身没有对缓存的数据进行持久性存储的设计,因此,在服务器端的memcached服务进程重启之后,存储在内存中的这些数据就会丢失。且当内存中缓存的数据容量达到启动时设定的内存值时,就自动使用LRU算法删除过期的缓存数据。

    开发Memcached的初衷就是仅为内存缓存而设计的,因此并没有过多考虑数据的永久存储问题。因此,如果使用memcached作为缓存数据服务,要考虑数据丢失后带来的问题,例如:是否可以重新生成数据,还有,在高并发场合数据丢失会不会导致网站架构雪崩。

    企业场景如何正确重启Memcached集群服务?在前端控制入口访问量。然后,启动Memcached集群并进行数据预热,所有数据都预热完毕后,在逐步的开放前端流量。


7.Memcached工作原理深入(内存管理机制)

    说Memcached内存管理机制之前,先说一下malloc。

    malloc的全称是memory allocation(动态内存分配),当无法知道内存具体位置的时,想要绑定真正的内存空间,就需要用到动态分配内存。

    早期的Memcached内存管理方式是通过malloc分配的内存,使用完后通过free来回收内存。这种方式容易产生内存碎片并降低操作系统对内存的管理效率。加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢,为了解决上述问题,Slab Allocator内存分配机制就诞生了。

    现在的Memcached利用Slab Allocation机制来分配和管理内存的。

    Slab Allocation内存分配机制原理是按照预先规定的大小,将内存给Memcached服务的内存预先分割成特定长度的内存块(chunk),再把尺寸相同的内存块(chunk)分成组(chunks slabclass),这些内存块不会释放,可以重复利用。

    Memcached服务器中保存着slab内空闲chunk的列表,根据该列选择chunk,然后将数据缓存于其中。当有数据存入时,Memcached根据接收到的数据大小,选择最合适数据大小的slab分配一一个能存下这个数据的最小内存快(chunk)。

    例如:有100个字节的一个数据,就会被分配存入112字节的一个内存块中,这样会有12字节被浪费掉,这部分空间不能被使用了,这也是SlabAllocator机制的一个缺点。


Memcached内存管理机制小结:

(1)memcached的早期内存管理机制为malloc(动态内存分配)

(2)malloc产生内存碎片,导致操作系统性能急剧下降

(3)slab内存分配机制可以解决内存碎片问题

(4)memcached服务的内存预先分割成特定长度的内存块,称为chunk,用于缓存数据的内存空间或内存块,相当于硬盘的block,只不过磁盘的每一个block都是相等的,而chunk只有同一个slab class内才是相等的

(5)slab class是特定大小的包含多个chunk的集合或者组,一个memcached包含多个slab class,每个slab class包含多个相同大小的chunk

(6)slab机制也有缺点,chunk的空间会浪费。


8.Memcached内存管理机制缺点及优化策略

    避免浪费内存的办法就是,预先计算出应用存入的数据大小,或把同一业务类型的数据存入一个Memcached服务器中,确保存入的数据大小相对均匀,这样就可以减少内存的浪费。还有一种办法是,在启动时指定"-f"参数,能在某种程度上控制内存组之间的大小差异。在应用中使用Memcached时,通常可以不重新设置这个参数,使用默认值1.25进行部署。如果想优化Memcached对内存的使用,可以考虑重新计算数据的预期平均长度,调整这个参数来获得合适的设置值。

-f<factor> chunk size growth factor(default:1.25!)

    memcachked在启动时制定Growth Factor因子(通过-f选项),就可以控制slab之间的差异。默认值为1.25

memcached -f 2 vv


二、Memcache部署

1.安装memcached

(1)安装libevent

wget http://www.monkey.org/~provos/libevent-1.4.13-stable.tar.gz

[root@memcached tools]# tar xf libevent-1.4.13-stable.tar.gz 

[root@memcached tools]# cd libevent-1.4.13-stable

[root@memcached libevent-1.4.13-stable]# ./configure

[root@memcached libevent-1.4.13-stable]# make && make install


(2)安装memcached

[root@memcached tools]# tar xf memcached-1.4.13.tar.gz 

[root@memcached tools]# cd memcached-1.4.13

[root@memcached memcached-1.4.13]# ./configure

[root@memcached memcached-1.4.13]# make && make install


(3)启动memcached

配置ld.so.conf路径防止启动memcached时报错

memcached -h

memcached:error while loading shared libraries:libevent-1.4.so.2:cannot open shared object file:

No such file or directory

echo "/usr/local/lib" >> /etc/ld.so.conf

ldconfig


[root@memcached ~]# memcached -d -c10240 -p11211 -m16 -P /var/run/memcached.pid -uroot -l 192.168.51.91

-d 作为守护进程在后台运行

-m 指定memcached服务可以缓存数据的最大内存。默认为64MB

-c 最大并发访问连接数(default:1024),按照服务器的并发访问量来设定

-p 指定memcached服务侦听TCP端口号,默认额外11211

-P 指定pid

-u 运行memcached的用户

-l 指定侦听的服务器IP地址

-vv以very vrebose模式启动,调试信息和错误输出到控制台

-P设置保存memcached的pid文件($$)

-h 显示所有可用选项

-f 调优因子


(4)检查启动结果

[root@memcached ~]# ps -ef|grep memcached

root     117028      1  0 19:38 ?        00:00:00 memcached -d -c10240 -p11211 -m16 -P /var/run/memcached.pid -uroot -l 192.168.51.91

root     117037 107682  0 19:38 pts/1    00:00:00 grep memcached

[root@memcached ~]# ss -ntulp|grep 11211

udp    UNCONN     0      0          192.168.51.91:11211                 *:*      users:(("memcached",117028,27))

tcp    LISTEN     0      128        192.168.51.91:11211                 *:*      users:(("memcached",117028,26))

[root@memcached ~]#


(5)写入数据检查结果

向memcached中添加数据:键值对

[root@memcached ~]# printf "set key001 0 0 10\r\nxiaoyi1234\r\n"|nc 192.168.51.91 11211

STORED

[root@memcached ~]# printf "get key001\r\n"|nc 192.168.51.91 11211

VALUE key001 0 10

xiaoyi1234

END

[root@memcached ~]#

[root@memcached ~]# telnet 192.168.51.91 11211

Trying 192.168.51.91...

Connected to 192.168.51.91.

Escape character is '^]'.

get key001

VALUE key001 0 10

xiaoyi1234

END



2.Memcached状态查看

stats 统计memcached的各种信息

stats settings 可以查看一些memcached设置

stats slabs查看slabs相关情况,通过这个命令能获取每个slabs的chunk size长度,从而确定数据到底保存在哪个slab

stats items查看items相关情况

stats sizes 查看存在的item个数和大小

stats cachedump查看key value

stats reset 重新统计数据


[root@memcached ~]# printf "stats\r\n"|nc 192.168.51.91 11211

STAT pid 117028 

STAT uptime 737

STAT time 1449229825

STAT version 1.4.13

STAT libevent 1.4.13-stable

STAT pointer_size 64

STAT rusage_user 0.003999

STAT rusage_system 0.029995

STAT curr_connections 5

STAT total_connections 22

STAT connection_structures 6

STAT reserved_fds 20

STAT cmd_get 5

STAT cmd_set 2

STAT cmd_flush 0

STAT cmd_touch 0

STAT get_hits 3

STAT get_misses 2

STAT delete_misses 0

STAT delete_hits 0

STAT incr_misses 0

STAT incr_hits 0

STAT decr_misses 0

STAT decr_hits 0

STAT cas_misses 0

STAT cas_hits 0

STAT cas_badval 0

STAT touch_hits 0

STAT touch_misses 0

STAT auth_cmds 0

STAT auth_errors 0

STAT bytes_read 250

STAT bytes_written 134

STAT limit_maxbytes 16777216

STAT accepting_conns 1

STAT listen_disabled_num 0

STAT threads 4

STAT conn_yields 0

STAT hash_power_level 16

STAT hash_bytes 524288

STAT hash_is_expanding 0

STAT expired_unfetched 0

STAT evicted_unfetched 0

STAT bytes 82

STAT curr_items 1

STAT total_items 2

STAT evictions 0

STAT reclaimed 0

END

####################################################

stats settings

STAT maxbytes 16777216

STAT maxconns 10240

STAT tcpport 11211

STAT udpport 11211

STAT inter 192.168.51.91

STAT verbosity 0

STAT oldest 0

STAT evictions on

STAT domain_socket NULL

STAT umask 700

STAT growth_factor 1.25

STAT chunk_size 48

STAT num_threads 4

STAT num_threads_per_udp 4

STAT stat_key_prefix :

STAT detail_enabled no

STAT reqs_per_event 20

STAT cas_enabled yes

STAT tcp_backlog 1024

STAT binding_protocol auto-negotiate

STAT auth_enabled_sasl no

STAT item_size_max 1048576

STAT maxconns_fast no

STAT hashpower_init 0

STAT slab_reassign no

STAT slab_automove no

END

#######################################################

stats slabs

STAT 1:chunk_size 96

STAT 1:chunks_per_page 10922

STAT 1:total_pages 1

STAT 1:total_chunks 10922

STAT 1:used_chunks 1

STAT 1:free_chunks 1

STAT 1:free_chunks_end 10920

STAT 1:mem_requested 82

STAT 1:get_hits 4

STAT 1:cmd_set 2

STAT 1:delete_hits 0

STAT 1:incr_hits 0

STAT 1:decr_hits 0

STAT 1:cas_hits 0

STAT 1:cas_badval 0

STAT 1:touch_hits 0

STAT active_slabs 1

STAT total_malloced 1048512

END

##############################################

stats items

STAT items:1:number 1

STAT items:1:age 7998

STAT items:1:evicted 0

STAT items:1:evicted_nonzero 0

STAT items:1:evicted_time 0

STAT items:1:outofmemory 0

STAT items:1:tailrepairs 0

STAT items:1:reclaimed 0

STAT items:1:expired_unfetched 0

STAT items:1:evicted_unfetched 0

END

######################################

stats sizes

STAT 96 1

END

####################################



3.关闭memcached,测试数据是否丢失

[root@memcached ~]# printf "set key001 0 0 10\r\nxiaoyi1234\r\n"|nc 192.168.51.91 11211

STORED

[root@memcached ~]# printf "get key001\r\n"|nc 192.168.51.91 11211

VALUE key001 0 10

xiaoyi1234

END


[root@memcached ~]# pkill memcached

[root@memcached ~]# memcached -d -c10240 -p11211 -m16 -P /var/run/memcached.pid -uroot -l 192.168.51.91

[root@memcached ~]# printf "get key001\r\n"|nc 192.168.51.91 11211

END


4.Memcached服务管理命令

操作memcached命令的语法:

<command name> <key><flags><exptime><bytes>\r\n

-<command name>是set,add,repalce

set"存储此数据"

add"存储此数据,只在服务器未保留此键值的数据时"

replace"存储此数据,只在服务器曾保留此键值的数据时"

-<key>是接下来的客户端所要求存储的数据的键值

-<flags>是在取回内容时,与数据和发送块一同保存服务器上的任意16位无符号整形(用十进制来书写)。客户端可以用它作为"位域"来存储-一些特定的信息;它对服务器是不透明的。

-<exptime>是终止时间。如果为0,该项永不过期(虽然它可能被删除,以便为其他缓存项目腾出位置)。如果非0(Unix时间戳或当前时刻的秒偏移),到达终止时间后,客户端无法再获得这项内容

-<bytes>是随后的数据区块的字节长度,不包括"\r\n".它可以是0(这时后面跟随一个空的数据区块)。

-<data block>是大段的8位数据,其长度由前面的命令行中的<bytes>指定。

-"STORED\r\n"表明成功。

-"NOT_S"表明数据没有被存储,但不是因为发生错误。这通常意味着add或replace命令的条件不成立,或者,项目已经位列删除队列。


三、监控Memcached

1.memcache.php

下载地址http://livebookmark.net/memcachephp/memcachephp.zip

vim memcache.php

.....

define('ADMIN_USERNAME','memcache'); // 定义用户名

define('ADMIN_PASSWORD','password'); // 定义密码

.....

$MEMCACHE_SERVERS[] = 'mymemcache-server:11211'; //定义要查看的ip和端口

$MEMCACHE_SERVERS[] = 'mymemcache-server2:11212'; //可添加多个

 


2.check_tcp

通过nagios的check_tcp脚本,信息量太大,不过可以将此信息通过自己编写脚本自定义监控memcached,不过有现成的Nagios-Plugins-Memcached插件

[root@memcached html]# /usr/local/nagios/libexec/check_tcp -H 192.168.51.91 -p 11211 -t 5 -E -s 'stats\r\nquit\r\n' -e 'uptime' -M crit

TCP OK - 0.001 second response time on port 11211 [STAT pid 119204

STAT uptime 9454

STAT time 1449493920

STAT version 1.4.13

STAT libevent 1.4.13-stable

STAT pointer_size 64

STAT rusage_user 0.193970

STAT rusage_system 0.250961

STAT curr_connections 5

STAT total_connections 270

STAT connection_structures 7

STAT reserved_fds 20

STAT cmd_get 2

STAT cmd_set 4

STAT cmd_flush 0

STAT cmd_touch 0

STAT get_hits 1

STAT get_misses 1

STAT delete_misses 0

STAT delete_hits 0

STAT incr_misses 0

STAT incr_hits 0

STAT decr_misses 0

STAT decr_hits 0

STAT cas_misses 0

STAT cas_hits 0

STAT cas_badval 0

STAT touch_hits 0

STAT touch_misses 0

STAT auth_cmds 0

STAT auth_errors 0

STAT bytes_read 1982

STAT bytes_written 264950

STAT limit_maxbytes 16777216

STAT accepting_conns 1

STAT listen_disabled_num 0

STAT threads 4

STAT conn_yields 0

STAT hash_power_level 16

STAT hash_bytes 524288

STAT hash_is_expanding 0

STAT expired_unfetched 0

STAT evicted_unfetched 0

STAT bytes 328

STAT curr_items 4

STAT total_items 4

STAT evictions 0

STAT reclaimed 0

END]|time=0.000525s;;;0.000000;5.000000


3.Nagios check_memcached插件

http://search.cpan.org/CPAN/authors/id/Z/ZI/ZIGOROU/Nagios-Plugins-Memcached-0.02.tar.gz


[root@memcached ~]# tar xf Nagios-Plugins-Memcached-0.02.tar.gz 

[root@memcached ~]# cd Nagios-Plugins-Memcached-0.02

[root@memcached Nagios-Plugins-Memcached-0.02]# perl Makefile.PL

*** Module::AutoInstall version 1.03

*** Checking for Perl dependencies...

[Core Features]

- Carp::Clan       ...missing.

- Cache::Memcached ...missing.

- FindBin          ...loaded. (1.50)

- Nagios::Plugin   ...missing.

- Time::HiRes      ...loaded. (1.9721)

==> Auto-install the 3 mandatory module(s) from CPAN? [y] y

Can't locate CPAN.pm in @INC (@INC contains: inc /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at inc/Module/AutoInstall.pm line 635, <STDIN> line 1.


yum install perl-CPAN -y

[root@memcached Nagios-Plugins-Memcached-0.02]# perl Makefile.PL

[root@memcached Nagios-Plugins-Memcached-0.02]# make && make install


command.cfg

define command{

        command_name    check_memcached_response

        command_line    $USER1$/check_memcached -H $HOSTADDRESS$ -w $ARG1$ -c $ARG2$

}


define command{

        command_name    check_memcached_size

        command_line    $USER1$/check_memcached -H $HOSTADDRESS$ --size-warning $ARG1$ --size-critical $ARG2$

}


define command{

        command_name    check_memcached_hit

        command_line    $USER1$/check_memcached -H $HOSTADDRESS$ --hit-warning $ARG1 --hit-critical $ARG2$

}


vim host.cfg

define host{

        use                     linux-server

        host_name               memcached

        alias                   memcached

        address                 192.168.51.91

        }


vim services.cfg

define service {

        use                             generic-service

        host_name                       memcached

        service_description             memcached

        check_command                   check_memcached_response!30!40


}


define service {

        use                             generic-service

        host_name                       memcached

        service_description             memcached_size

        check_command                   check_memcached_size!30!40

}


define service {

        use                             generic-service

        host_name                       memcached

        service_description             memcached_hit

        check_command                   check_memcached_hit!40!30

}




[root@memcached objects]# /usr/local/nagios/libexec/check_memcached -H 192.168.51.91 -w 30 -c 40

Base class package "Nagios::Plugin" is empty.

    (Perhaps you need to 'use' the module which defines that package first,

    or make that module available in @INC (@INC contains: /usr/local/nagios/libexec/../lib /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .).

 at /usr/local/share/perl5/Nagios/Plugins/Memcached.pm line 6

BEGIN failed--compilation aborted at /usr/local/share/perl5/Nagios/Plugins/Memcached.pm line 6.

Compilation failed in require at /usr/local/nagios/libexec/check_memcached line 12.

BEGIN failed--compilation aborted at /usr/local/nagios/libexec/check_memcached line 12.

[root@memcached objects]#

wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo

yum -y install perl-Params-Validate perl-Math-Calc-Units perl-Regexp-Commonperl-Class-Accessor perl-Config-Tiny perl-Nagios-Plugin.noarch


[root@memcached Nagios-Plugins-Memcached-0.02]# /usr/local/nagios/libexec/check_memcached -H 192.168.51.91

MEMCACHED OK - OK


 





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章