Memcache 基础笔记

(一):基础概念

  1. memcache是什么?

Memcache 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

  1. memcache的工作原理?

theory.jpg

RDBMS :关系数据库管理系统(Relational Database Management System)。
memcached:
php有两个memcache客户端,一个是php memcached, 一个是php memcache。客户端的memcached
相当于memcache的Plus版,实际在操作上和memcache几乎类似,当然作为memcache的升级版,memcached在稳定性和速度上更好,php操作memcached提供了更多的方法。在php官方的手册中分别搜索memcached和memcache 能发现他们的异同点。

  1. memcache的主要特点?
  1. 协议简单 基于C/S架构(Client/Server)
    2.基于libevent的事件处理
    3.内置内存存储方式
    4.互不通信的分布式内纯缓存服务器
  1. memcache的使用场景?

1.因为memcache是不能持久化数据的,一旦memcache宕机或者重启之类的,原来存入的数据都会丢失,所以对一些数据的安全性要求不高的可以考虑使用memcache

2.因为memcache存储的单个对象的最大是1M所以,当有一些体积相对较小,但是频繁被访问的数据时,可以是考虑memcache

3.当一个系统有大量的动态内容时,存在大量的读取数据库的操作,造成数据库负载过高时,可以考虑使用memcache做缓存来缓解数据库压力

4.多台服务器需要共享某些数据的时候,可以考虑使用memcache,例如:session共享

5.小结:memcache基本就是做缓存用的,为的是缓解服务器的压力,提高系统悉能

(二) 安装memcache
1.准备工具

1.1 : Xshell
1.2 :一个可用的LAMP/LNMP环境
1.3:我测试的是LAMP CentOS7+Apache(2.4.6)+MySql(5.6.35)+PHP(5.416)

2.安装基本流程

2.1 安装memcached的服务器端
一般在服务器端安装memcached得首先安装libevent库才行,但是在CentSO上使用yum方式安装可以解决这种依赖

yum install memcached


2.2 安装php的memcache扩展

yum install php-memcache

2.3 重启一下服务器

3.memcache安装后测试

3.1 开启memcache服务器端

2017-03.png

3.1.1memcached指令参数基础解释

//在memcache的服务器端,我们可以通过memcached -help查该指令有那些参数,我们只解释下他的基础参数的意思
//例如 指令 /usr/bin/memcached -d -l 127.0.0.1 -p 11211 -m 150 -u root
-d 表示是守护进程
-l 连接的ip地址
-p memcached服务器监听的端口
-m 分配给memcached服务的最大的内存,单位是MB,默认是64M
-u 以谁的身份运行,示例中的是root用户运行,实际中少这么用,权限太高了
-c 同时最大的连接数 默认是1024
-n 最小分配空间 key+value+flags 默认是48

3.2 查看php的memcache安装是否成功
3.2.1 进入你应用的根目录 例如:/var/www/html/ 下
3.2.2. 新建一个文件 vim phpinfo.php

<?php
  phpinfo();
?>

3.2.3 使用浏览器访问该文件 如果出现如下信息

2017-03.png

3.2.4 表示php的memcache扩展开启成功了
3.2.5 注意: 当你的memcache都安装好了,在服务器上写的php脚本,通过客户端浏览器访问却没有什么内容返回的情况,我们首先查看一下Linux上的访问日志和错误日志,我是的LAMP环境,访问日志和错误日志都是放在了默认的位置 /var/log/httpd 目录下.打开access_log
access_log.png

状态码是200 表示访问是ok的
我们再看错误日志error_log


error.png

我们看到最近的一次错误是许可被拒绝了
基本分析是可能和权限,安全保护有关(SELinux,防火墙等)
此处我临时关闭SElinux即可 指令如下

setenforce 0  

(三):PHP操作memcache

  1. 简单的讲memcache是php对内存操作的一种媒介
  1. 既然是对内存的操作,不能免俗的就要从增删改查四部曲开始
  2. php操作memcache,就和操作一个普通的类是一样的

php连接memcache服务器

  1. 我们进入项目的根目录(例如:/var/www/html/)新建一个文件con.php
<?php

//新建一个memcache对象$mem
$mem = new Memcache;
//连接memcache服务器
//connect("memcache服务器地址","memcache服务器使用的端口号")
$mem->connect("127.0.0.1",11211);
//查看memcache服务器的统计状态
print_r($mem->getStats());

```php
<?php

//新建一个memcache对象$mem
$mem = new Memcache;
//向连接池中添加一个memcache服务器
/*
*使用addServer方法也可以连接memcache服务器上,引用php手册上的说法是:
*"使用这个方法的时候网络连接并不会立刻建立,而是直到真正使用的时候才建立。 因此在加
*入大量服务器到连接池中时也是没有开销的,因为它们可能并不会被使用"
*/
$mem->addServer("127.0.0.1",11211);
//查看memcache服务器的统计状态
print_r($mem->getStats());

  1. 通过浏览器访问该文件


    2017-03.png

    2.1 返回的统计信息是一个数组,我们大概了解一下返回的统计信息的意思

    [pid] => 37344   服务器的进程id
    [uptime] => 21672     服务从启动到当前所经过的时间,单位是秒
    [time] => 1489951190    服务器所在主机当前系统的时间,单位是秒
    [version] => 1.4.15    memcached的版本号
    [libevent] => 2.0.21-stable
    [pointer_size] => 64     服务器所在主机操作系统的指针大小
    [rusage_user] => 1.174806    
    [rusage_system] => 0.931503
    [curr_connections] => 8     表示当前系统打开的连接数
    [total_connections] => 33   表示从memcached服务启动到当前时间,系统打开过的连接的总数
    [connection_structures] => 9   
    [reserved_fds] => 20
    [cmd_get] => 14   累积获取数据的数量
    [cmd_set] => 1     累积保存数据的数量
    [cmd_flush] => 0
    [cmd_touch] => 0
    [get_hits] => 12    表示获取数据成功的次数
    [get_misses] => 2  表示获取数据失败的次数
    [delete_misses] => 0 表示删除数据失败的次数
    [delete_hits] => 0      表示删除数据命中的次数
    [incr_misses] => 0   表示增加一个元素失败的次数
    [incr_hits] => 0        表示增加一个元素命中的次数
    [decr_misses] => 0   表示减少一个元素失败的次数
    [decr_hits] => 0        表示减少一个元素命中的次数
    [cas_misses] => 0
    [cas_hits] => 0
    [cas_badval] => 0
    [touch_hits] => 0
    [touch_misses] => 0
    [auth_cmds] => 0
    [auth_errors] => 0
    [bytes_read] => 270    memcached服务器从网络读取的总的字节数
    [bytes_written] => 12788    memcached服务器发送到网络的总的字节数。
    [limit_maxbytes] => 157286400  memcached服务缓存允许使用的最大字节数
    [accepting_conns] => 1
    [listen_disabled_num] => 0
    [threads] => 4    被请求的工作线程的总数量
    [conn_yields] => 0
    [hash_power_level] => 16
    [hash_bytes] => 524288
    [hash_is_expanding] => 0
    [bytes] => 0
    [curr_items] => 0
    [total_items] => 1
    [expired_unfetched] => 0
    [evicted_unfetched] => 0
    [evictions] => 0
    [reclaimed] => 0

2.2 我们看到使用php操作memcache,首先是实例化一个memcache的对象,然后建立一个memcache服务端的连接.

php操作memcache

添加数据###

1.1 例如文件位置 : /var/www/html/con.php

<?php
$mem  = Memcache;
$mem->connect('127.0.0.1',11211);
//memcache缓存数据的结构是基于 key -> value (键值)的
//add('键名','值','是否压缩','多少秒后失效')
$mem->add('one','故人西辞黄鹤楼',0,60);  

1.2 我们再用一个文件验证是否存入 文件位置:/var/www/html/test.php

<?php
$mem  = Memcache;
$mem->connect('127.0.0.1',11211);
echo date("Y-m-d H:i:s");
echo $mem->get('one');  

1.3 通过浏览器访问执行,结果如下

2017-03-25.png

超过设定的时间后就失效了

2017-03-25.png

1.4 我们也可以使用set('键名','值',是否压缩,失效时间)来添加数据

<?php
$mem  = Memcache;
$mem->connect('127.0.0.1',11211);
//set('键名','值','是否压缩','多少秒后失效')
$mem->add('one','故人西辞黄鹤楼',0,60);  
$mem->set('one','烟花三月下扬州',0,60);  

1.5 我们再获取一下这个值

2017-03-25.png

1.6 add()和set()方法的区别: add()添加一个值,如果这个值存在,则添加失败
set()添加一个值,如果这个值存在,则替换掉原有的

删除数据###

2.1 修改 /var/www/html/test.php 文件

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
echo date("Y-m-d H:i:s");
echo $mem->get('one')."<br />";
$mem->delete('one');
$one = $mem->get('one');
if(empty($one))
{
        echo "数据已经删除";
}

2.2 执行该文件后的效果

2017-03-25.png
2017-03-25.png

2.3 使用flush()方法清除已经存储的所有数据
2.3.1 修改 /var/www/html/con.php 文件并执行

<?php
$mem = new Memcache;
$mem->addServer("127.0.0.1",11211);
$mem->add('one','故人西辞黄鹤楼',false,0);
$mem->set('two','烟花三月下扬州',0,0);
$mem->set('three','孤帆远影碧空尽',0,0);
$mem->set('four','唯见长江天际流',0,0);

2.3.2 修改 /var/www/html/test.php 文件并执行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
$result = $mem->get(array('one','two','three','four'));
echo "<pre>";
var_dump($result);

2.3.3 结果如下

2017-03-25.png

2.3.4 再修改 /var/www/html/test.php 文件并执行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
$mem->flush();
$result = $mem->get(array('one','two','three','four'));
echo "<pre>";
var_dump($result);

2.3.5 结果如下

2017-03-25.png

修改数据###

3.1 php修改memcache的数据一般有两个方法set() 和replace()
3.1.1再修改 /var/www/html/test.php 文件并执行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
//replace('被更新的键','新值','是否压缩','过期时间')
$flag = $mem->replace('four','欢迎来到扬州',0,0);
if($flag === FALSE)
{
   echo "更新数据失败";
}else{
  echo "更新数据成功";
}


$result = $mem->get(array('one','two','three','four'));
echo "<pre>";
var_dump($result);

3.1.2 通过浏览器访问test.php文件后的结果如下:

2017-03-25.png

3.1.3 我们再次修改 /var/www/html/test.php 文件并执行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
//更新一个不存在的键 例如:five
$flag = $mem->replace('five','火星欢迎您',0,0);
if($flag === FALSE)
{
   echo "更新数据失败";
}else{
  echo "更新数据成功";
}


$result = $mem->get(array('one','two','three','four'));
echo "<pre>";
var_dump($result);

3.1.4 执行后结果如下:

2017-03-25.png

3.2 set()和replace是区别是:

当数据存在的时候,set()方法和replace()方法都能更新(修改),作用相同
当数据不存在的时候,set()方法会添加这样一条数据,replace()方法会返回FALSE

查询数据###

//memcache有关查询的几个方法
get()获取memcache上key的值,前面有示例,既能是单一的key值也可以是一组key的数组
getStatus()获取当前memcache服务器的统计信息
getServerStatus('服务器地址','端口号')用于获取一个服务器的在线/离线状态,返回一个服务器的状态,0表示服务器离线,非0表示在线。 
getExtendedStats()缓存服务器池中所有服务器统计信息,如果缓存池中有多台memcache服务器,就将这些服务器的信息以二维数组的形式都返回
//例如,我向连接池中添加两台memcache服务器:
$mem->addServer("127.0.0.1",11211);
$mem->addServer("127.0.0.1",11212);
$stats = $mem->getExtendedStats();
print_r($stats);
//返回的信息格式将会是:
Array
(
        [127.0.0.1:11211]=>Array
          (
              .........
          )
        [127.0.0.1:11212]=>Array
          (
              .........
          )
)

增加或者减少一个元素的值###

increment('要增加值的元素的键','增加的量');
decrement('要减少值的元素的键','减少的量');

我们修改 /var/www/html/con.php 文件并执行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
$mem->set('num',4,0,0);

我们修改 /var/www/html/test.php 文件并执行

<?php
$mem = new Memcache;
$mem->connect("127.0.0.1",11211);
$mem->increment('num',3);
echo $mem->get('num');

结果如下:

2017-03-26.png

键 , 压缩 ,过期时间,缓存过期,分配内存耗尽

  1. 键(key) : 因为memcache是基于键和值的存储方式,memcache中键的命名很可以很随意,但是我们还是推荐比较有意义键名,key的最大长度是250个字节
  2. 压缩 :因为memcache存储单个item最大数据是在1MB内.所以当我们进行存储,会考虑是否开启压缩
//e.g:
bool memcache::set(key,value,是否压缩[0/1],失效时间);

2.1 压缩会节省更多的内存空间,但是也会带来额外的CPU开销,运行速度相对会慢
2.2 未压缩,占用的内存空间小,但是运行速度快
2.3memcache 支持的最大存储对象是1M,所以在将单个大于1M的内容存储到memcache的时候需要开压缩

  1. 有效时间:
memcache::set("key","value",是否压缩,有效时间);
memcache::add("key","value",是否要锁,有效时间);

memcache的有效时间单位是秒(s),手册的解释是"当前写入缓存的数据的失效时间",设置有效时间有两种写法,并且有区别

//这种设置的有效时间的最大值是2592000秒既30天,但是要是有效时间大于30天怎么办?
memcache::set("home","love",0,2592000);
//这样这种时间戳的方式可以设置大于30天的有效时间
memcache::set("hope","love",0,time()+2592001);
  1. 当我们设置的一个缓存超过的有效期,那么这个缓存就"过期"了,不能再使用了,那么些过期的缓存数据会被memcache清除掉吗?会的,memcache清除过期的数据是采用的一种"懒惰"的机制,过期后不会立刻清除掉,而是当再次通过get()方式获取缓存时删除过期的数据
  2. 我们再开启memcache的时候曾经通过-m这个参数给开启的这个memcache分配一定内存大小,可是当这个分配的内存被使用殆尽的时候会怎么样呢?当分配的内存用尽,此时再向memcache中存入数据,那么memcache就会将最近不常用的数据删除掉,这种机制就是LRU(least recently used )

php操作memcache 基础示例

我们模拟一个场景,我现在的user表(仅三个字段)中存在52W条数据,我要取出最新的2万条数据.

分析:第一次访问,memcache中没有这些数据,我们就从DB中取得这些数据,并且将这些数据存入memcache中,当需要访问相同的数据的时候,直接从memcache中提供这些数据

  1. 准备数据


    mysql.png
  2. 编写基本脚本(php)文件
    我们在根目录下新建一个文件 vim /var/www/html/test2.php
<?php
$starttime = microtime(true);
echo $starttime;
echo "<hr />";
function getmemcache($sql,Memcache $memacche)
{
$key  = md5($sql);
      $data = $memcache->get($key);
       if(!$data)
      {
         try{
            $pdo = new PDO("mysql:host=localhost;dbname=test",'root','123456');
            }catch(PDOException $e){
              die($e->getMessage());
            }
            $stmt = $pdo->prepare($sql);
            $stmt->execute();
            $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
            $memcache->set($key,$data,MEMCACHE_COMPRESSED, 0);
  }

return $data;
}
$mem = new Memcache();
$mem->connect('127.0.0.1',11211);
$sql = "select * from user order by id desc limit 0,20000";
$data = getmemcache($sql,$mem);
echo "<pre>";
print_r($data);
$mem->close();
$endtime = microtime(true);
echo "<hr />";
echo $endtime.'<br />';
echo '执行时间'.round($endtime-$starttime,3).'秒';


3.通过客户端浏览器第一次访问test2.php文件

one.png

4.再次访问test2.php文件

one.png

5.我们可以看到第二访问是从memcache中获取测数据,应为我在test2.php文件中有2W条数据输出,感觉还是耗时很多,我们将数据输出那段代码注释掉,再次并且清空一下memcache缓存,再次访问test2.php文件

three.png
four.png

学习本是一个自我修正的过程,总结中有许多的不足,万望不吝赐教

[参考资料]:
1.http://php.net/manual/zh/class.memcache.php php手册memcache部分
2.http://www.w3cschool.cn/memcached/ W3Cschool memcached部分
3.http://blog.csdn.net/heiyeshuwu/article/details/3950532 Memcached原理和使用详情
[拓展资料]:

  1. 《大型网站技术架构》李智慧著
  2. http://www.songyawei.cn/content/5008?utm_source=tuicool&utm_medium=referral memcache和memcached的区别
  3. http://www.cnblogs.com/caoxiaojian/p/5715568.html Memcache介绍与应用场景
  4. http://yw666.blog.51cto.com/11977292/1910163?utm_source=tuicool&utm_medium=referral memcache缓存服务器
  5. http://www.cnblogs.com/crazyacking/p/5793239.html 走进缓存的世界
  6. http://www.imooc.com/learn/527 近距离探索memcache缓存
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容