(一):基础概念
- memcache是什么?
Memcache 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。
- memcache的工作原理?
RDBMS :关系数据库管理系统(Relational Database Management System)。
memcached:
php有两个memcache客户端,一个是php memcached, 一个是php memcache。客户端的memcached
相当于memcache的Plus版,实际在操作上和memcache几乎类似,当然作为memcache的升级版,memcached在稳定性和速度上更好,php操作memcached提供了更多的方法。在php官方的手册中分别搜索memcached和memcache 能发现他们的异同点。
- memcache的主要特点?
- 协议简单 基于C/S架构(Client/Server)
2.基于libevent的事件处理
3.内置内存存储方式
4.互不通信的分布式内纯缓存服务器
- 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服务器端
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 使用浏览器访问该文件 如果出现如下信息
3.2.4 表示php的memcache扩展开启成功了
3.2.5 注意: 当你的memcache都安装好了,在服务器上写的php脚本,通过客户端浏览器访问却没有什么内容返回的情况,我们首先查看一下Linux上的访问日志和错误日志,我是的LAMP环境,访问日志和错误日志都是放在了默认的位置 /var/log/httpd 目录下.打开access_log
状态码是200 表示访问是ok的
我们再看错误日志error_log
我们看到最近的一次错误是许可被拒绝了
基本分析是可能和权限,安全保护有关(SELinux,防火墙等)
此处我临时关闭SElinux即可 指令如下setenforce 0
(三):PHP操作memcache
- 简单的讲memcache是php对内存操作的一种媒介
- 既然是对内存的操作,不能免俗的就要从增删改查四部曲开始
- php操作memcache,就和操作一个普通的类是一样的
php连接memcache服务器
- 我们进入项目的根目录(例如:/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());
-
通过浏览器访问该文件
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 通过浏览器访问执行,结果如下
超过设定的时间后就失效了
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 我们再获取一下这个值
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 执行该文件后的效果
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 结果如下
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 结果如下
修改数据###
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文件后的结果如下:
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 执行后结果如下:
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');
结果如下:
键 , 压缩 ,过期时间,缓存过期,分配内存耗尽
- 键(key) : 因为memcache是基于键和值的存储方式,memcache中键的命名很可以很随意,但是我们还是推荐比较有意义键名,key的最大长度是250个字节
- 压缩 :因为memcache存储单个item最大数据是在1MB内.所以当我们进行存储,会考虑是否开启压缩
//e.g: bool memcache::set(key,value,是否压缩[0/1],失效时间);
2.1 压缩会节省更多的内存空间,但是也会带来额外的CPU开销,运行速度相对会慢
2.2 未压缩,占用的内存空间小,但是运行速度快
2.3memcache 支持的最大存储对象是1M,所以在将单个大于1M的内容存储到memcache的时候需要开压缩
- 有效时间:
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);
- 当我们设置的一个缓存超过的有效期,那么这个缓存就"过期"了,不能再使用了,那么些过期的缓存数据会被memcache清除掉吗?会的,memcache清除过期的数据是采用的一种"懒惰"的机制,过期后不会立刻清除掉,而是当再次通过get()方式获取缓存时删除过期的数据
- 我们再开启memcache的时候曾经通过-m这个参数给开启的这个memcache分配一定内存大小,可是当这个分配的内存被使用殆尽的时候会怎么样呢?当分配的内存用尽,此时再向memcache中存入数据,那么memcache就会将最近不常用的数据删除掉,这种机制就是LRU(least recently used )
php操作memcache 基础示例
我们模拟一个场景,我现在的user表(仅三个字段)中存在52W条数据,我要取出最新的2万条数据.
分析:第一次访问,memcache中没有这些数据,我们就从DB中取得这些数据,并且将这些数据存入memcache中,当需要访问相同的数据的时候,直接从memcache中提供这些数据
准备数据
- 编写基本脚本(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文件
4.再次访问test2.php文件
5.我们可以看到第二访问是从memcache中获取测数据,应为我在test2.php文件中有2W条数据输出,感觉还是耗时很多,我们将数据输出那段代码注释掉,再次并且清空一下memcache缓存,再次访问test2.php文件
学习本是一个自我修正的过程,总结中有许多的不足,万望不吝赐教
[参考资料]:
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原理和使用详情
[拓展资料]:
- 《大型网站技术架构》李智慧著
- http://www.songyawei.cn/content/5008?utm_source=tuicool&utm_medium=referral memcache和memcached的区别
- http://www.cnblogs.com/caoxiaojian/p/5715568.html Memcache介绍与应用场景
- http://yw666.blog.51cto.com/11977292/1910163?utm_source=tuicool&utm_medium=referral memcache缓存服务器
- http://www.cnblogs.com/crazyacking/p/5793239.html 走进缓存的世界
- http://www.imooc.com/learn/527 近距离探索memcache缓存