缓存是指临时文件交换区,电脑把最常用的文件从存储器里提出来临时放在缓存里,就像把工具和材料搬上工作台一样,这样会比用时现去仓库取更方便。因为缓存 往往使用的是RAM(断电即掉的非永久储存),所以在忙完后还是会把文件送到硬盘等存储器里永久存储。电脑里最大的缓存就是内存条了,最快的是CPU上镶 的L1和L2缓存,显卡的显存是给GPU用的缓存,硬盘上也有16M或者32M的缓存。千万不能把缓存理解成一个东西,它是一种处理方式的统称! Cache是 “以空间换时间”策略的典型应用模式,是提高系统性能的一种重要方法。缓存的使用在大访问量的情况下能够极大的减少对数据库操作的次数,明显降低系统负荷 提高系统性能。相比页面的缓存,结果集是一种“原始数据”不包含格式信息,数据量相对较小,而且可以再进行格式化,所以显得相当灵活。由于PHP是“一边 编译一边执行”的脚本语言,某种程度上也提供了一种相当方便的结果集缓存使用方法——通过动态include相应的数据定义代码段的方式使用缓存。如果在 RamDisk上建缓存的话,效率应该还可以得到进一步的提升。以下是一小段示例代码,供参考。(参考:PHP数据缓存技术) WEB程序获取信息的方式主要是查询数据库,当数据库不是很大的情况下不会有太大的问题.然而,随着网站的发展,数据库呈几何级数的方式增长的时候,就会出现瓶颈.于是PHP缓存技术诞生了。…
PHP: Memcached安装, Memcache/Memcached的PHP操作手册, Memcached使用, Memcached教程
1. memcache和memcached区别
Memcache是什么?
Memcache是一个自由和开放源代码、高性能、分配的内存对象缓存系统。用于加速动态web应用程序,减轻数据库负载。它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个Hash表,Memcached自管理这些Hash表。
Memcached是简单而强大的。它简单的设计促进迅速部署,易于发展所面临的问题,解决了很多大型数据缓存。它的API可供最流行的语言。
Memcache官方网站:http://memcached.org/
Memcached又是什么?
Memcache是该系统的项目名称,Memcached是该系统的主程序文件(字母d可以理解为daemon),以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,使用共享内存存取数据。简单来说就是一个免费开源并且高性能的分布式内存对象缓存系统,主要用于加速动态 Web 程序,减轻数据库负载。
Memcached 可以存储来自调用数据库和 API,或者页面渲染生成的任意类型的数据(字符串,对象)到内存中,也可以直接中内存中去读取。它的 API 支持目前大部分流行的编程语言,Memcached 的官方网站:http://memcached.org/
启动 Memcached 服务端是通过启动一个 memcached 的程序来实现的,这里的 d 的英文是 daemon,意思就是常驻进程的意思。所以Memcache 是对这个内存缓存的一个常用称呼,而Memcached 是这个缓存数据库的实际运行程序。
你也可以这么理解memcached是memcache升级版。
PHP 的 Memcached 客户端
PHP 有两个 Memcached 客户端:“PHP Memcache 扩展” 和 “PHP Memcached 扩展”,这就是是我们搞混的地方。
PHP Memcache 扩展用 PHP 实现的,支持面向对象和面向过程两种接口,2004年就实现了,是老客户端,而且功能少,属性也可设置的少。
函数列表:http://php.net/manual/zh/book.memcache.php
PHP Memcached 扩展基于 libmemcached 开发的,使用 libmemcached 库提供的 API 与 Memcached 服务进行交互,只支持面向对象的接口,2009年才实现,Memcached 扩展功能更加完善,支持的函数更多,比如支持批量操作,现在一般建议使用 Memcached 扩展。
函数列表:http://php.net/manual/zh/book.memcached.php
下面是一个支持功能对照列表:
对比 | Memcache | Memcached |
---|---|---|
发布日期 | 2004-06-08 | 2009-01-29 (beta) |
仍在维护? | Yes | Yes |
第三方依赖 | None | libmemcached |
Key自动修复 | Yes | No |
Append/Prepend | No | Yes |
自动序列化 | Yes | Yes |
二进制协议 | No | Optional |
CAS | No | Yes |
压缩 | Yes | Yes |
超时设置 | Connect Only | Various Options |
一致性哈希 | Yes | Yes |
延迟Get | No | Yes |
Multi-Get | Yes | Yes |
Session支持 | Yes | Yes |
指定Server get/set | No | Yes |
数字存储 | Converted to Strings | Yes |
支持长连接? | Yes | Yes |
必须同时安装服务端和客户端
如果安装了 Memcached 服务端不安装扩展,那么 PHP 无法操控 Memcached。
同样如果安装了 PHP Memcached 扩展(PHP Memcache 和 PHP memcached 两者选择一个),但是没有安装 Memcached 服务端,那么这个就无法使用。
只有同时安装了 Memcached 服务端和 PHP 客户端扩展才可以提高动态网站性能。
在 WordPress 使用 Memcached
在 WordPress 如何使用 Memcached,请查看这篇文章:http://blog.wpjam.com/m/wordpress-memcached/
根据不同的 PHP 扩展下载不同的 WordPress Memcached 插件(这个很重要):
PHP Memcache 扩展:http://wordpress.org/extend/plugins/memcached/
PHP Memcached 扩展:https://wordpress.org/plugins/memcached-is-your-friend/
2. memcache和memcached安装
1)安装Memcache服务端
sudo apt-get install memcached
安装完Memcache服务端以后,我们需要启动该服务:
memcached -d -m 128 -p 11111 -u root
这里需要说明一下memcached服务的启动参数:
-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25-n 最小分配空间,key+value+flags默认是48
-h 显示帮助
2)安装Memcache客户端(PHP5为示例)
sudo apt-get install php7.2-memcache
安装完以后我们需要在php.ini里进行简单的配置,打开/etc/php5/apache2/php.ini文件在末尾添加如下内容:
[Memcache] ; 是否在遇到错误时透明地向其他服务器进行故障转移。 memcache.allow_failover = On ; 接受和发送数据时最多尝试多少个服务器,只在打开memcache.allow_failover时有效。memcache.max_failover_attempts = 20 ;数据将按照此值设定的块大小进行转移。此值越小所需的额外网络传输越多。 ; 如果发现无法解释的速度降低,可以尝试将此值增加到32768。 memcache.chunk_size = 8192 ; 连接到memcached服务器时使用的默认TCP端口。 memcache.default_port = 11111 ; 控制将key映射到server的策略。默认值”standard”表示使用先前版本的老hash策略。 ; 设为”consistent”可以允许在连接池中添加/删除服务器时不必重新计算key与server之间的映射关系。 ;memcache.hash_strategy = “standard”; 控制将key映射到server的散列函数。默认值”crc32″使用CRC32算法,而”fnv”则表示使用FNV-1a算法。 ; FNV-1a比CRC32速度稍低,但是散列效果更好。 ;memcache.hash_function = “crc32″
最后,保存php.ini,执行sudo/etc/init.d/apache2 restart重启Apache。
Memcache和Memcached 其实是一个东西,只是php中要是用的扩展不一样, 2009年左右有人丰富memcache的用法和性能,编写了一个libmemcached是独立第三方client library,才有了memcached ,用法也有了很大的改进比如添加了 getMulti() 批量获取键值
windows下只能安装php_memcache.dll 扩展并不存在 php_memcached.dll, 所以windows 中只能使用$mcd = new Memcache() 不能使用new Memcached()
3. Memcache 类
$memcache = new Memcache; $memcache->connect('127.0.0.1', 11211); $memcache->pconnec('127.0.0.1', 11211); // 打开一个到服务器的持久化连接 , 连接不会在脚本执行结束后或者close()被调用后关闭 $memcache->addServer('123.57.210.55', 11211,$persistent,$weight); // 向连接池中添加一个memcache服务器 $persistent 是否持久化连接 $weight 控制桶的数量提升被选中的权重 $timeout 表示连续持续时间 $memcache->set('name', 'TK'); // 默认存储不压缩 不过期 , 其中字符串和数值直接存储,其他类型序列化后存储 set其实是add方法和replace方法集合 $memcache->set('email', 'julylovin@163.com',MEMCACHE_COMPRESSED,5); // MEMCACHE_COMPRESSED设置存储是否压缩 , 5表示5秒后过期但是最大只能设置2592000秒(30天) 如果设置为0 表示永不过期, 可以设置将来的时间戳 $memcache->set('info',array('age'=>'26','salary'=>'1000')); // 可以直接存储数组,redis中存储需要手动serialize()序列化 $memcache->add('counter', '10', MEMCACHE_COMPRESSED, 0); //如果键值存在会返回false , 如果不存在, 和set方法一样,生成一个counter的key并赋值10 $memcache->replace ('counter', '10'); //如果键值不存在会返回false , 如果存在, 替换counter的值为10 $memcache->increment('counter', 3); // 首先将元素当前值转换成数值然后减去value 操作counter键值+3 若键不存在 则返回false 不能用于压缩的键值操作,否则get键会失败 $memcache->decrement('counter', 3); // 操作counter键值-3 , 若键不存在 则返回false $memcache->delete('counter', 3); // 操作删除键counter , 3表示3秒内删除,默认是0即立即删除 $memcache->flush(); //flush()立即使所有已经存在的元素失效 $memcache->getExtendedStats (); // 返回一个二维关联数据的服务器统计信息。数组的key由host:port方式组成 $memcache->getServerStatus ('127.0.0.1'); // 获取返回一个服务器的在线/离线状态 0表示离线 非0在线 $memcache->getStats(); // 获取服务器统计信息 $memcache->getVersion(); // 返回服务器版本信息 $memcache->setCompressThreshold ($threshold, $min_saving); // 开启大值自动压缩 $threshold设置压缩阀值 2000字节 ,即字节数大于2K 就压缩 $min_saving 0--1之间 0.2表示压缩20% $memcache->setServerParams('memcache_host', 11211, 1, 15, true, '_callback_memcache_failure'); // $memcache->addServer('memcache_host', 11211, false, 1, 1, -1, false); 已经通过addServer 配置过服务器 使用setServerParams 重新设置配置信息
4. Memcached 类
此次练习我是在linux上安装了phpstorm,linux平台开发配置看我的其他文章
$memcached = new Memcached(); // 必须安装memcached扩展 不会安装看我的相关文章 #server_key名词解释# #当台服务IP和端口完全连通好之后,构成一个hash环,$server_key才会生效 #$server_key 只是为了存储的key打个标记 比如有三台 memcache服务器 (A B C ) , 指定 server_key 'master-a' 'master-b' 'master-c' 分别存储 会员 订单 日志 等等 $memcached->addServer('192.168.206.128',11211); // 连接服务器 $memcached->setOption(Memcached::OPT_COMPRESSION, false); //配置存储不压缩,压缩value不利于递增递减 $memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true); // $memcached->addServers(array( //添加多台服务器分布式 array('192.168.206.128', 11311, 20), array('192.168.206.128', 11411, 30) )); $memcached->flush(1); //1秒内清除所有元素 $memcached->set('name','TK'); $memcached->setByKey('server_master_db','mage','28'); # 指定 server_key server_master_db 存储键mage $memcached->setMulti(array('salary'=>'3000','email'=>'julylovin@163.com')); // 存储多个元素 $memcached->setMultiByKey('server_master_db', array('salary'=>'3000','email'=>'julylovin@163.com')); // 'server_master_db'服务器 存储多个元素 $memcached->add('name','TK'); // 键name不存在添加value 否则添加失败 $memcached->addByKey('server_master_db','mname','MTK'); $memcached->append('key','-816'); // 键key的value后追加字符串 -816 $memcached->appendByKey('server_master_db','mname','-923'); $memcached->prepend('name','pre-') ; #向一个已存在的元素前面追加数据 $memcached->prependByKey('server_master_db','name','pre-') ; # 使用server_key自由的将key映射到指定服务器 向一个已存在的元素前面追加数据 $memcached->get('name'); $memcached->get('name',null,$cas); # 第2参数指定缓存回掉函数 ,不指定传null # 如果元素被找到,并且返回变量 $cas 内部是通过引用变量回传的 $memcached->getByKey('server_master_db','mname'); # 从特定的服务器检索元素 $memcached->getAllKeys(); // bug 我一致返回是false $memcached->cas($cas, 'name', 'TangKang'); #要与$memcached->get('name',null,$cas) 方法搭配用 才可以拿到 $cas变量 #它仅在当前客户端最后一次取值后,该key 对应的值没有被其他客户端修改的情况下, 才能够将值写入 #这是Memcached扩展比Memcache扩展一个非常重要的优势 在这样一个系统级(Memcache自身提供)的冲突检测机制(乐观锁)下, 我们才能保证高并发下的数据安全 $memcached->casByKey($cas,'server_master_db', 'name', 'TangKang'); $memcached->increment('age','1'); #增加数值元素的值 如果元素的值不是数值类型,将其作为0处理 $memcached->incrementByKey('server_master_db','age','1'); # 用于识别储存和读取值的服务器 $memcached->decrement('age','1'); #减少数值元素的值 如果元素的值不是数值类型,将其作为0处理 $memcached->decrementByKey('server_master_db','age','1'); # 用于识别储存和读取值的服务器 $memcached->getDelayed(array('name', 'age'), true, null); # 请求多个元素, 如果with_cas设置为true,会同时请求每个元素的CAS标记 指定一个result callback来替代明确的抓取结果 $memcached->getDelayedByKey('server_master_db',array('name', 'age'), true, null); $memcached->fetch(); # 搭配 $memcached->getDelayed()使用, 从最后一次请求中抓取下一个结果 $memcached->fetchAll(); #抓取最后一次请求的结果集中剩余的所有结果 $memcached->getMulti(array('name', 'age')); #检索多个元素 $memcached->getMultiByKey('server_master_db',array('mname', 'mage')); # 从特定服务器检索多个元素 # 与 $this->memcached->fetchAll() 搭配使用 $memcached->getOption(Memcached::OPT_COMPRESSION); # 获取Memcached的选项值 $memcached->getResultCode() ; # 返回最后一次操作的结果代码 Memcached::RES_NOTSTORED $memcached->getResultMessage() ; # 返回最后一次操作的结果描述消息 $memcached->getServerByKey('server_master_db') ; # 获取一个key所映射的服务器信息 $memcached->getServerList() ; # 获取服务器池中的服务器列表 $memcached->getStats() ; # 获取服务器池的统计信息 $memcached->getVersion() ; # 获取服务器池中所有服务器的版本信息 $memcached->isPersistent() ; #判断当前连接是否是长连接 $memcached->replace('name','pre-julylovin') ; #set()类似,但是如果 服务端不存在key, 操作将失败 $memcached->replaceByKey('server_master_db','name','pre-julylovin') ; #setBykey()类似,但是如果 服务端不存在key, 操作将失败 $memcached->resetServerList() ; //清楚服务器池信息 $memcached->setOption(Memcached::OPT_PREFIX_KEY, "widgets") ; #设置一个memcached选项 $memcached->setOptions(array()) ; #设置一个memcached选项 $memcached->setSaslAuthData($username , $password ) ; #setSaslAuthData 方法不存在 $memcached->touch('name', 10) ; #设置键name 10秒后过期(只适用30天之内的秒数) ,30天以后请设置时间戳 $memcached->touchByKey('server_master_db','name',10) ; $memcached->delete('age',10); #10秒(秒数/时间戳)内删除一个元素 这个键已经存在删除队列 该键对应的get、add、replace命令都不可用,直到删除 $memcached->deleteByKey('server_master_db','age'); $memcached->deleteMulti(array('age','name')); #传入array删除多个key $memcached->deleteMultiByKey('server_master_db',array('age','name')); $memcached->quit(); # 关闭所有打开的链接
5. 实例:
memcache 是 key => value 的方式,一个key 对应 一个 value 。
memcache一般多用于存储大型能开销的数据,比如SQL结果集。将其序列化或者json_encode后存入memcache中,并命名为一个唯一的key值。下次则直接从memcached中获取该值。
注:经过测试serialize 后的string 存入memcached 比 json_encode后的string要快很多。 若直接将array存入memcached实际上memcached底层有将array进行 serialize(array); (我这里一直记错!!)
如下实例: 有数据table threads. 我们将其结果缓存起来。
// 首先进行查询memcached中threads_list是否为非空集合 $list = json_decode($memcached->get("threads_list")); if(!$list){ $query = $db->query("SELECT * FROM `threads` "); while($value = $db->fetch_array($query)){ $list[] = $value; } //进行memcached插入 //$memcached->set(键值,内容,失效时间); $memcached->set("threads_list",json_encode($list),86400); } print_r($list);
<?php //实例化一个memcache对象 $mem=new Memcache; //链接一台memcahe服务 $mem->connect('localhost','11211'); //准备SQL语句 $sql='SELECT * FROM user'; //设置一个键名 $key=md5($sql); $data=$mem->get($key); //第二次之后的查询 if(!$data){ try{ //链接mysql $dsn="mysql:host=localhost;dbname=bbs"; $pdo=new PDO($dsn,'root','root'); //设置字符集 $pdo->exec('set names utf8'); $stmt=$pdo->prepare($sql); $stmt->execute(); $data=$stmt->fetchAll(); //把数据存储到memcache中(第一次查询) $mem->add($key,$data); }catch(PDOException $e){ echo $e->getMessage(); } } $mem->close(); print_r($data); ?>
6. 应用场景
一、如果需要缓存的数据只是key-value 这样简单的结构时,采用Memcache,足够稳定可靠。如果有持久化需求、存储、排序等一系列复制操作时,或者对数据结构和处理有高级要求的应用,选择Redis。
二、memcache使用场景:
1、在动态系统中减少数据库负载,提升性能,做缓存,适合多读少写,大数据量的情况(如人人网大量查询用户信息、好友信息、文章信息等)。它的一个总原则是将经常需要从数据库读取的数据缓存在memcached中,这些数据也分为几类:
(1)经常被读取并且实时性要求不强可以等到自动过期的数据。例如网站首页最新文章列表、某某排行等数据。也就是虽然新数据产生了,但对用户体验不会产生任何影响的场景。这类数据就使用典型的缓存策略,设置一过合理的过期时间,当数据过期以后再从数据库中读取。当然你得制定一个缓存清除策略,便于编辑或者其它人员能马上看到效果。
(2)经常被读取并且实时性要求强的数据。比如用户的好友列表,用户文章列表,用户阅读记录等。这类数据首先被载入到memcached中,当发生更改(添加、修改、删除)时就清除缓存。在缓存的时候,我将查询的SQL语句md5()得到它的 hash值作为key,结果数组作为值写入memcached,并且将该SQL涉及的table_name以及hash值配对存入memcached中。 当更改了这个表时,我就将与此表相配对的key的缓存全部删除。
2、秒杀功能:一个人下单,要牵涉数据库读取,写入订单,更改库存,及事务要求, 对于传统型数据库来说,压力是巨大的。
可以利用 memcached 的 incr/decr 功能, 在内存存储 count 库存量, 秒杀 1000 台每人抢单主要在内存操作,速度非常快,抢到 count < =1000 的号人,得一个订单号,这时再去另一个页面慢慢支付。
三、不适用memcached的业务场景:
1、缓存对象的大小大于1MB;
2、key的长度大于250字符(所以我们把一些key先md5再存储);
3、应用运行在不安全的环境中Memcached为提供任何安全策略,仅仅通过telnet就可以访问到memcached。如果应用运行在共享的系统上,需要着重考虑安全问题;
4、业务本身需要的是持久化数据。
四、Redis场景:适用于对读写效率要求都很高,数据处理业务复杂和对安全性要求较高的系统(如新浪微博的计数和微博发布部分系统,对数据安全性、读写要求都很高)、Pub/Sub构建实时消息系统、统计。
区别:
1、存储方式:Memcache把数据全部存在内存之中,断电后会挂掉,数据不能超 过内存大小。Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启时可以再次加载进行使用。(RDB快照和AOF日志两 种持久化方式)。
2、Redis支持数据的备份,及master-slave模式的数据备份。
3、数据支持类型:Redis在数据支持上要比Memcache多得多。
4、使用底层模型不同:新版本的Redis直接自己构建了VM机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
5、 redis有一个致命缺陷 当内存满了时 dump数据cpu占用100%。
总结:
1、Redis使用最佳方式是全部数据in-memory。
2、Redis更多场景是作为Memcache的替代者来使用。
3、当需要除key/value之外的更多数据类型支持时,使用Redis更合适。
4、当存储的数据不能被剔除时,使用Redis更合适。
5、如果要说内存使用效率,使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。当然,这和你的应用场景和数据特性有关。
更多:在PHP中使用memcached提高动态网站性能, memcached, memcache, memcached数据库缓存类
本文:PHP: Memcached安装, Memcache/Memcached的PHP操作手册, Memcached使用, Memcached教程