memcached安装及配置
一、memcached介绍
Memcached是国外社区网站LiveJournal团队开发的,高性能分布式内存缓存服务器,其目的是为了通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、 提高可扩展性。
- 数据结构简单(key-value),数据存放在内存里,不支持持久化
- 多线程
- 基于c/s架构,协议简单
- 基于libevent的事件处理
- 自主内存存储处理(slab allowcation)
- 数据过期方式:Lazy Expiration 和 LRU
二、Memcached的数据流向
- web从DB上获取到查询结果
- 把结果存储到memcached中
- 再次用到该结果,从缓存中读取
三、Slab Allocation的原理
Slab Allocation机制:整理内存以便重复使用。
在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。 但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。
Slab Allocation的原理相当简单。将分配的内存分割成各种尺寸的块(chunk), 并把尺寸相同的块分成组(chunk的集合)。而且,slab allocator还有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用。
每个chunk集合被称为slab。
Memcached的内存分配以Page为单位,Page默认值为1M,可以在启动时通过-I参数来指定。
Slab是由多个Page组成的,Page按照指定大小切割成多个chunk。
四、Growth factor
增长因子,Memcached在启动时通过-f选项可以指定 Growth Factor因子。该值控制chunk大小的差异,默认值为1.25。
通过memcached-tool命令查看指定Memcached实例的不同slab状态,可以看到各Item所占大小(chunk大小)差距为1.25。
五、Memcached的数据过期方式
1. Lazy Expiration
Memcached 内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期,这种技术被称为lazy(惰性)expiration。因此,Memcached不会在过期监视上耗费CPU时间。
2. LRU
Memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,当内存空间不足时(无法从slab class获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。从缓存的实用角度来看,该模型十分理想。
六、Memcached的安装
memcached安装与一般应用程序相同,configure、make、make install就行了。
当然也可以使用安装系统包含的rpm包,虽然这个包的版本可能会有些老旧。
yum install -y memcached libmemcached libevent
默认启动:
systemctl start memcached
以及手动启动,可以定义参数:
/usr/bin/memcached -u memcached -p 11211 -m 64 -c 最大并发数
选项说明:
- -u 指定运行的用户
- -p 使用的TCP端口。默认为11211
- -m 最大内存大小。默认为64M
- -vv 用very vrebose模式启动,调试信息和错误输出到控制台
- -d 作为daemon在后台启动
还可以在/etc/sysconfig/memcached文件中修改配置参数,以便在默认启动的时候,指定监听端口、内存、最大连接数以及监听主机。
七、查看服务状态
在memcached中,运行state命令可以查看memcached服务的状态信息。
使用memcached-tool工具查看:
memcached-tool 127.0.0.1:11211 stats
#127.0.0.1:11211 Field Value
accepting_conns 1
auth_cmds 0
auth_errors 0
bytes 0
bytes_read 20
bytes_written 2052
cas_badval 0
cas_hits 0
cas_misses 0
cmd_flush 0
cmd_get 0
cmd_set 0
cmd_touch 0
conn_yields 0
connection_structures 11
curr_connections 10
curr_items 0
decr_hits 0
decr_misses 0
delete_hits 0
delete_misses 0
evicted_unfetched 0
evictions 0
expired_unfetched 0
get_hits 0
get_misses 0
hash_bytes 524288
hash_is_expanding 0
hash_power_level 16
incr_hits 0
incr_misses 0
libevent 2.0.21-stable
limit_maxbytes 67108864
listen_disabled_num 0
pid 3051
pointer_size 64
reclaimed 0
reserved_fds 20
rusage_system 0.032412
rusage_user 0.064825
threads 4
time 1523207503
total_connections 14
total_items 0
touch_hits 0
touch_misses 0
uptime 2088
version 1.4.15
其中cmd_get表示总的get次数,get_hits表示get的总命中次数,命中率 = get_hits/cmd_get。
get_hits是一个历史数据,curr_items是当前存储的数据。
get_hits/curr_items=命中率(实际访问成功)
还有其它两种命令也可以查看:
# 需要安装nmap-ncat(yum install nc)
echo stats |nc 127.0.0.1 11211
如果安装了libmemcached这个面向C/C++语言的客户端库,就会安装memstat这个命令。使用方法很简单,可以用更少的步骤获得与telnet相同的信息,还能一次性从多台服务器获得信息。
memstat --servers=127.0.0.1:11211
八、Memcached命令行
可以使用telnet工具进入memcached:
telnet 127.0.0.1 11211
# memcached的基本语法格式:
# <command name> <key> <flags> <exptime> <bytes>
# <data block>
# 设置
set key2 0 30 2
ab
STORED
- (set、add、replace) set表示按照相应的
存储该数据,没有的时候增加,有的时候覆盖;add表示按照相应的 添加该数据,但是如果该 已经存在则会操作失败;replace表示按照相应的 替换数据,但是如果该 不存在则操作失败。 客户端需要保存数据的key; 是一个16位的无符号的整数(以十进制的方式表示)。该标志将和需要存储的数据一起存储,并在客户端get数据时返回。客户端可以将此标志用做特殊用途,此标志对服务器来说是不透明的; 为过期的时间,若为0表示存储的数据永远不过期(但可被服务器算法:LRU 等替换)。如果非0(unix时间或者距离此时的秒数),当过期后,服务器可以保证用户得不到该数据(以服务器时间为标准)。 需要存储的字节数,当用户希望存储空数据时 可以为0; - 需要存储的内容,输入完成后,最后客户端需要加上\r\n(直接点击Enter)作为结束标志。
获取
get key2
VALUE key2 0 2
ab
END
九、Memcached数据导出和导入
因为memcached的数据结构原因,memcached服务器在重启的时候,需要提前备份数据,不然会造成数据丢失。
导出:
memcached-tool 127.0.0.1:11211 dump > data.txt
导入:
nc 127.0.0.1 11211 < data.txt
# 若nc命令不存在,yum install nc
注意:
导出的数据是带有一个时间戳的,这个时间戳就是该条数据过期的时间点,如果当前时间已经超过该时间戳,那么是导入不进去的;
如果过期时间设置为零,那么在数据导出的时候服务会自动标记时间戳,再次导入之后便会过期,无法导入。
十、memcached连接PHP
PHP 有两个 Memcached 客户端:“PHP Memcache 扩展” 和 “PHP Memcached 扩展”,这就是是我们搞混的地方。其中memcache最早是在2004年2月开发的,最后更新是在2013年4月,而 memcached 最早是在2009年1月开发的,最后更新是在2014年1月更新的,所以一些老的代码可能还在用memcache扩展。memcached后来出现,并且大部分框架都支持memcached,现在相对较流行。
1. memcached模块
首先是memcached模块,目前这模块的pecl版本不支持php7,好在经过寻找,在GitHub社区找到了它的分支。在安装它之前需要先安装libmemcached,而且对版本也是有要求,建议安装最新的1.0.18,否则会出现如下错误:
checking for libmemcached location... configure: error: memcached support requires libmemcached. Use --with-libmemcached-dir=<DIR> to specify the prefix where libmemcached headers and library are located
ERROR: `/var/tmp/memcached/configure --with-libmemcached-dir=no' failed
libmemcached的安装过程如下:
cd /usr/local/src
wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz
tar zxf libmemcached-1.0.18.tar.gz
cd libmemcached-1.0.18
./configure
make && make install
其次安装php-memcached-3.0.4:
cd /usr/local/src/php-7.1.6/ext/
wget https://github.com/php-memcached-dev/php-memcached/archive/v3.0.4.tar.gz
tar zxf v3.0.4.tar.gz
cd php-memcached-3.0.4
/usr/local/php7/bin/phpize
./configure --with-php-config=/usr/local/php7/bin/php-config
这里可能会报错:
configure: error: no, sasl.h is not available. Run configure with --disable-memcached-sasl to disable this check
再次配置编译参数:
./configure --with-php-config=/usr/local/php7/bin/php-config --disable-memcached-sasl
# 编译安装:
make && make install
# 返回如下信息说明安装成功
Installing shared extensions: /usr/local/php7/lib/php/extensions/no-debug-zts-20160303/
查看这个目录即可看到该模块已经添加进去
ls /usr/local/php7/lib/php/extensions/no-debug-zts-20160303/
memcached.so
然后在PHP的配置文件中添加这样一条,重启httpd即可
extension = "memcached.so"
2. memcache模块
在根据php官网给出的地址安装memcache最新版本的时候,make后报错:
/usr/local/src/memcache-2.2.3/memcache.c:40:40: fatal error: ext/standard/php_smart_str.sh: No such file or directory
#include "ext/standard/php_smart_str.h"
php_smart_str.h是给字符串预处理动态申请内存空间,类似于操作系统中内存以页为单位分配,它的好处是对齐内存地址,提高访问速度。
而在PHP7版本中,已经把此文件升级为php_smart_string.h,好在memcached后续版本已经更上php7的脚步,开发出了pecl-memcache,其源码发布在GitHub社区:
cd /usr/local/src/php-7.1.6/ext/
git clone https://github.com/websupport-sk/pecl-memcache.git
cd pecl-memcache
/usr/local/php7/bin/phpize
./configure --with-php-config=/usr/local/php7/bin/php-config
make && make install
然后也是在php.ini配置文件中加入:
extension = "memcache.so"