一、Memcached介绍


    是国外社区网站LiveJournal团队开发,通过缓存数据库查询结果,减少数据库访问次数,从而提高动态web站点性能。官方站点 http://memcached.org/

    memcached属于键值(Key-Value)存储数据库,适合储存用户信息,比如会话、配置文件、参数、购物车等等。这些信息一般都是和ID(键)挂钩,这种情景下键值数据库是个很好的选择。

1、Memcached特性

    (1)基于c/s架构,协议简单

    (2)基于libevent的事件处理

    (3)自主内存存储处理(slab allowcation)

    (4)数据过期方式:Lazy Expiration和LRU

2、memcached数据流

wKiom1ZKz7Hz3nzjAAHdKSEYjFo666.png

3、Slab Allowcationde

    Slab Allowcationde原理:将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合),每个chunk集合被称为slab。

    Memcached的内存分配以Page为单位,Page默认值为1M,可以在启动时通过-l参数来指定。

    Slab是由多个Page组成的,Page按照指定大小切割成多个chunk。其结构如图:

wKiom1ZK16HAp-ocAAE_1-Lh4zc621.jpg


4、Growth Factor

    memcached在启动时通过 -f 选项可以指定 Growth Factor 因子。该值控制slab之间的差异,chunk大小的差异。默认值为1.25。通过memcached-tool查看指定memcached实例的不同slab状态,可以看到各Item所占大小(chunk大小)差距为1.25

命令:#memcached-tool 127.0.0.1:11211 display


5、Memcached数据过期方式

(1)Lazy Expiration:

    memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,memcached不会再过期监视上耗费CPU时间。

(2)LRU:

    memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新纪录时空间不足的情况,此时就要使用名为Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,当内存空间不足时(无法从slab class获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。从缓存的实用角度来看,该模型十分理想。


二、Memcached安装


[root@centos ~]# yum install -y epel-release

[root@centos ~]# yum install -y libevent memcached libmemcached

[root@centos ~]# /etc/init.d/memcached start           

[root@centos ~]# netstat -lnp |grep memcached        //可查看memcached端口号为11211

tcp         0      0 0.0.0.0:11211        0.0.0.0:*           LISTEN      1931/memcached

tcp         0      0 :::11211                :::*                   LISTEN      1931/memcached

udp        0      0 0.0.0.0:11211        0.0.0.0:*                           1931/memcached

udp        0      0 :::11211                :::*                                   1931/memcached

[root@centos ~]# ps aux |grep memcached           //查看进程

498       1931  0.1  0.0  58188   896 ?        Ssl  03:51   0:00 memcached -d -p 11211 -u memcached -m 64 -c 1024 -P /var/run/memcached/memcached.pid

root      1939  0.0  0.0   5980   748 pts/0    S+   03:52   0:00 grep memcached

1、Memcached启动参数说明

-d 是启动一个守护进程。

-p 是设置Memcached监听的端口,默认是11211。

-u 是运行Memcached的用户,如果当前为root的话,需要使用此参数指定用户。

-m 是分配给Memcached使用的内存数量,单位是MB,这里是64MB。

-l 是监听的服务器IP地址,默认没有。

-c 是最大运行的并发连接数,默认是1024。

-P 是设置保存Memcached的pid文件。

启动的相关参数在 /etc/init.d/memcached 和 /etc/sysconfig/memcached 中定义,若要修改启动参数,只有修改 /etc/sysconfig/memcached 才有效,修改 /etc/init.d/memcached 不会生效。

2、查看Memcached运行状态

[root@centos ~]# 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           7

              bytes_written           0

                  cas_badval           0

                       cas_hits           0

                  cas_misses           0

                   cmd_flush           0

                     cmd_get           0                 

                      cmd_set           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

                      evictions           0

                       get_hits           0               //命中数量

                   get_misses           0

                       incr_hits           0

                   incr_misses           0

              limit_maxbytes          67108864

      listen_disabled_num          0

                               pid          1931

                  pointer_size          32

              rusage_system          0.119981

                  rusage_user          0.031995

                        threads           4

                             time          1448396035

         total_connections          11

                   total_items           0

                         uptime          1332

                         version          1.4.4

注意:命中率为 get_hits/cmd_get 大于80%才行。

3、查看Memcached服务状态

[root@centos ~]# memstat --servers=127.0.0.1:11211              //需安装libmemcached

Listing 1 Server


Server: 127.0.0.1 (11211)

         pid: 1931

         uptime: 1379

         time: 1448396082

         version: 1.4.4

         pointer_size: 32

         rusage_user: 0.32994

         rusage_system: 0.122981

         curr_items: 0

         total_items: 0

         bytes: 0

         curr_connections: 10

         total_connections: 12

         connection_structures: 11

         cmd_get: 0

         cmd_set: 0

         get_hits: 0

         get_misses: 0

         evictions: 0

         bytes_read: 0

         bytes_written: 0

         limit_maxbytes: 67108864

         threads: 4


三、Memcached基本操作


1、memcached命令

[root@centos ~]# yum install -y telnet*         //先安装telnet

[root@centos ~]# vim /etc/xinetd.d/telnet

 disable         = no

[root@centos ~]# service xinetd start            //开启telnet服务和xinetd

[root@centos ~]# telnet 127.0.0.1 11211        //连接memcached

Trying 127.0.0.1...

Connected to 127.0.0.1.

Escape character is '^]'.

set key1 0 300 2                 //储存数据

ab

STORED

get key1

VALUE key1 0 2

ab

END


replace key1 111 400 3       //替换数据

abc

STORED

get key1

VALUE key1 111 3

abc

END


delete key1                       //删除数据

DELETED

get key1

END


quit                                  //退出连接

2、memcached语法规则

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

1)<command name>可以是 "set"、"add"、"replace"、"delete".

    "set"表示按照相应的<key>存储该数据;若没有则增加,若有则覆盖

    "add"表示按照相应的<key>添加该数据;若该<key>已存在,则操作失败

    "replace"表示按照相应的<key>替换数据;若该<key>不存在,则操作失败

    "delete"表示删除相应的<key>;若该<key>不存在,则操作失败

2)<key>客户端需要保存数据的key。

3)<flags> 是一个16位的无符号的整数(以十进制的方式表示)。

4)<exptime>过期时间。

    若为0,表示存储的数据永远不过期(但可被服务器算法LRU等替换)

    若为非0,当过期后,服务器可以保证用户得不到该数据(以服务器时间为标准)

5)<bytes> 需要存储的字节数,当用户希望存储空间数据时<bytes>可以为0。

6)\r\n 在Windows下是Enter键。

7)<data block>需要存储的内容,输入完成后,最后客户端需要加上"\r\n"(直接Enter)作为“命令头”的结束标志。


四、PHP 连接 Memcached


1、安装php的memcache扩展

[root@centos ~]# cd /usr/local/src/

[root@centos src]# wget http://www.lishiming.net/data/p_w_upload/forum/memcache-2.2.3.tgz

[root@centos src]# tar -zvxf memcache-2.2.3.tgz

[root@centos memcache-2.2.3]# /usr/local/php/bin/phpize

[root@centos memcache-2.2.3]# ./configure --with-php-config=/usr/local/php/bin/php-config

[root@centos memcache-2.2.3]# make

[root@centos memcache-2.2.3]# make install

Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/

2、配置

[root@centos memcache-2.2.3]# ls /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/

memcache.so  opcache.so

[root@centos memcache-2.2.3]# vim /usr/local/php/etc/php.ini

extension_dir = "/usr/local/php/ext"   //指定目录,默认是在no-debug-non-zts-20131226

extension = memcache.so                  //末尾添加一行

[root@centos memcache-2.2.3]# mkdir /usr/local/php/ext

[root@centos memcache-2.2.3]# cp /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/memcache.so /usr/local/php/ext

[root@centos memcache-2.2.3]# ls /usr/local/php/ext

memcache.so

3、检测是否连接成功

[root@centos memcache-2.2.3]# /usr/local/php/bin/php -m |grep memcache    //有memcache模块

memcache

[root@centos memcache-2.2.3]# vim 1.php            //编辑测试的php脚本

<?php

//连接Memcache Memcache

$mem = new Memcache;

$mem->connect("localhost", 11211);

//保存数据

$mem->set('key1', 'This is first value', 0, 60);

$val = $mem->get('key1');

echo "Get key1 value: " . $val ."<br>";

//替换数据

$mem->replace('key1', 'This is replace value', 0, 60);

$val = $mem->get('key1');

echo "Get key1 value: " . $val . "<br>";

//保存数组数据

$arr = array('aaa', 'bbb', 'ccc', 'ddd');

$mem->set('key2', $arr, 0, 60);

$val2 = $mem->get('key2');

echo "Get key2 value: ";

print_r($val2);

echo "<br>";

//删除数据

$mem->delete('key1');

$val = $mem->get('key1');

echo "Get key1 value: " . $val . "<br>";

//清除所有数据

$mem->flush();

$val2 = $mem->get('key2');

echo "Get key2 value: ";

print_r($val2);

echo "<br>";

//关闭连接

$mem->close();

?>

[root@centos memcache-2.2.3]# /usr/local/php/bin/php 1.php       //运行测试脚本

Get key1 value: This is first value<br>Get key1 value: This is replace value<br>Get key2 value: Array

(

    [0] => aaa

    [1] => bbb

    [2] => ccc

    [3] => ddd

)

<br>Get key1 value: <br>Get key2 value: <br>

显示上面的内容,说明解析成功。


五、Memcached 共享 Session


本实例是lamp/lnmp环境中实现,通用方法。

1、编辑php.ini

[root@centos memcache-2.2.3]# vim /usr/local/php/etc/php.ini   

找到:

session.save_handler = files                                  //注释掉

添加两行:

session.save_handler = "memcache"

session.save_path = "tcp://127.0.0.1:11211"           //若是远程memcached,则为远程机器ip

2、测试

1)在lamp下测试:

[root@centos memcache-2.2.3]# cd /usr/local/apache2/htdocs

[root@centos htdocs]# vim session.php

<?php

session_start();

if (!isset($_SESSION['TEST'])) {

$_SESSION['TEST'] = time();

}

$_SESSION['TEST3'] = time();

print $_SESSION['TEST'];

print "<br><br>";

print $_SESSION['TEST3'];

print "<br><br>";

print session_id();

?>

[root@centos htdocs]# /usr/local/apache2/bin/apachectl start       //开启httpd服务

[root@centos htdocs]# curl -x127.0.0.1:80 localhost/session.php     //curl测试php脚本

1448477726<br><br>1448477726<br><br>h581d37pj6jbl9md4r67tim317

[root@centos htdocs]# telnet 127.0.0.1 11211

Trying 127.0.0.1...

Connected to 127.0.0.1.

Escape character is '^]'.

get h581d37pj6jbl9md4r67tim317                           //get key

VALUE h581d37pj6jbl9md4r67tim317 0 37

TEST|i:1448477726;TEST3|i:1448477726;

END

由测试结果可知,memcached数据库获取了key内容,在lamp环境下,memcached实现了session共享。

2)在lnmp下测试:

[root@centos htdocs]# cp session.php /usr/local/nginx/html/            //复制脚本到nginx环境下

[root@centos html]# /usr/local/apache2/bin/apachectl stop              //关闭httpd服务

[root@centos html]# service nginx start                                             //开启nginx服务

[root@centos html]# curl -x127.0.0.1:80 localhost/session.php

1448479908<br><br>1448479908<br><br>pmvlj2af2iq5to6hn1viuuo0n0

[root@centos html]# telnet 127.0.0.1 11211

Trying 127.0.0.1...

Connected to 127.0.0.1.

Escape character is '^]'.

get pmvlj2af2iq5to6hn1viuuo0n0

VALUE pmvlj2af2iq5to6hn1viuuo0n0 0 37

TEST|i:1448479908;TEST3|i:1448479908;

END

由上面测试结果可知,在lnmp环境下,memcached也实现了session共享。


注意说明

上面实例是在lamp/lnmp环境中通用的方法,另外一种方法是单独在lamp或者lnmp下实现,不用修改php.ini文件,直接修改下面对应的配置文件:

1)lamp

在 httpd.conf 对应的虚拟主机中添加(可以针对每个虚拟主机进行memcached共享session)

session.save_handler = "memcache"

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

2)lnmp

在 php-fpm.conf 对应的pool中添加

session.save_handler = "memcache"

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