设为首页 收藏本站
查看: 969|回复: 0

[经验分享] 关于php的缓存技术

[复制链接]

尚未签到

发表于 2017-3-26 12:05:29 | 显示全部楼层 |阅读模式
  在比较大型的项目中,如果没有用到缓存技术,那简直糟糕透了,java中常用dbcp或者proxool 连接池,相比java,php用的是页面缓存。下面是网络上抓来的一些缓存技术。
普遍缓存技术
数据缓存:这里所说的数据缓存是指数据库查询缓存,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件中,以后同样的查询结果就直接从缓存表或文件中获得。
  用的最广的例子看Discuz的搜索功能,把结果ID缓存到一个表中,下次搜索相同关键字时先搜索缓存表。
举个常用的方法,多表关联的时候,把附表中的内容生成数组保存到主表的一个字段中,需要的时候数组分解一下,这样的好处是只读一个表,坏处就是两个数据同步会多不少步骤,数据库永远是瓶颈,用硬盘换速度,是这个的关键点。
<!--more-->
页面缓存:
  每次访问页面的时候,都会先检测相应的缓存页面文件是否存在,如果不存在,就连接数据库,得到数据,显示页面并同时生成缓存页面文件,这样下次访问的时候页面文件就发挥作用了。(模板引擎和网上常见的一些缓存类通常有此功能)
  时间触发缓存:
  检查文件是否存在并且时间戳小于设置的过期时间,如果文件修改的时间戳比当前时间戳减去过期时间戳大,那么就用缓存,否则更新缓存。
  内容触发缓存:
  当插入数据或更新数据时,强制更新缓存。
  静态缓存:
  这里所说的静态缓存是指静态化,直接生成HTML或XML等文本文件,有更新的时候重生成一次,适合于不太变化的页面,这就不说了。
  以上内容是代码级的解决方案,我直接CP别的框架,也懒得改,内容都差不多,很容易就做到,而且会几种方式一起用,但下面的内容是服务器端的缓存方案,非代码级的,要有多方的合作才能做到
  内存缓存:
  Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。
java的dbcp我想就是内存缓存。
下面看各种php缓存的实现。
1、页面缓存

class cache {   
//缓存目录   
var $cacheRoot        = "./cache/";   
//缓存更新时间秒数,0为不缓存   
var $cacheLimitTime   = 0;   
//缓存文件名   
var $cacheFileName    = "";   
//缓存扩展名   
var $cacheFileExt     = "php";   
/*   
* 构造函数   
* int $cacheLimitTime 缓存更新时间   
*/   
function cache( $cacheLimitTime ) {   
if( intval( $cacheLimitTime ) )     
$this->cacheLimitTime = $cacheLimitTime;   
$this->cacheFileName = $this->getCacheFileName();   
ob_start();   
}   
/*   
* 检查缓存文件是否在设置更新时间之内   
* 返回:如果在更新时间之内则返回文件内容,反之则返回失败   
*/   
function cacheCheck(){   
if( file_exists( $this->cacheFileName ) ) {   
$cTime = $this->getFileCreateTime( $this->cacheFileName );   
if( $cTime + $this->cacheLimitTime > time() ) {   
echo file_get_contents( $this->cacheFileName );   
ob_end_flush();   
exit;   
}   
}   
return false;   
}   
/*   
* 缓存文件或者输出静态   
* string $staticFileName 静态文件名(含相对路径)   
*/   
function caching( $staticFileName = "" ){   
if( $this->cacheFileName ) {   
$cacheContent = ob_get_contents();   
//echo $cacheContent;   
ob_end_flush();   
if( $staticFileName ) {   
$this->saveFile( $staticFileName, $cacheContent );   
}   
if( $this->cacheLimitTime )   
$this->saveFile( $this->cacheFileName, $cacheContent );   
}   
}   
/*   
* 清除缓存文件   
* string $fileName 指定文件名(含函数)或者all(全部)   
* 返回:清除成功返回true,反之返回false   
*/   
function clearCache( $fileName = "all" ) {   
if( $fileName != "all" ) {   
$fileName = $this->cacheRoot . strtoupper(md5($fileName)).".".$this->cacheFileExt;   
if( file_exists( $fileName ) ) {   
return @unlink( $fileName );   
}else return false;   
}   
if ( is_dir( $this->cacheRoot ) ) {   
if ( $dir = @opendir( $this->cacheRoot ) ) {   
while ( $file = @readdir( $dir ) ) {   
$check = is_dir( $file );   
if ( !$check )   
@unlink( $this->cacheRoot . $file );   
}   
@closedir( $dir );   
return true;   
}else{   
return false;   
}   
}else{   
return false;   
}   
}   
/*   
* 根据当前动态文件生成缓存文件名   
*/   
function getCacheFileName() {   
return  $this->cacheRoot . strtoupper(md5($_SERVER["REQUEST_URI"])).".".$this->cacheFileExt;   
}   
/*   
* 缓存文件建立时间   
* string $fileName   缓存文件名(含相对路径)   
* 返回:文件生成时间秒数,文件不存在返回0   
*/   
function getFileCreateTime( $fileName ) {   
if( ! trim($fileName) ) return 0;   
if( file_exists( $fileName ) ) {     
return intval(filemtime( $fileName ));   
}else return 0;   
}   
/*   
* 保存文件   
* string $fileName  文件名(含相对路径)   
* string $text      文件内容   
* 返回:成功返回ture,失败返回false   
*/   
function saveFile($fileName, $text) {   
if( ! $fileName || ! $text ) return false;   
if( $this->makeDir( dirname( $fileName ) ) ) {   
if( $fp = fopen( $fileName, "w" ) ) {   
if( @fwrite( $fp, $text ) ) {   
fclose($fp);   
return true;   
}else {   
fclose($fp);   
return false;   
}   
}   
}   
return false;   
}   
/*   
* 连续建目录   
* string $dir 目录字符串   
* int $mode   权限数字   
* 返回:顺利创建或者全部已建返回true,其它方式返回false   
*/   
function makeDir( $dir, $mode = "0777" ) {   
if( ! $dir ) return 0;   
$dir = str_replace( "\\", "/", $dir );   
$mdir = "";   
foreach( explode( "/", $dir ) as $val ) {   
$mdir .= $val."/";   
if( $val == ".." || $val == "." || trim( $val ) == "" ) continue;   
if( ! file_exists( $mdir ) ) {   
if(!@mkdir( $mdir, $mode )){   
return false;   
}   
}   
}   
return true;   
}   
}   
?>
include( "cache.php" );   
$cache = new cache(30);   
$cache->cacheCheck();   
echo date("Y-m-d H:i:s");   
$cache->caching();   

  
2、内存缓存
Memcache类。
Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。
它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。
为什么会有Memcache和memcached两种名称?
其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名,
Memcache官方网站:http://www.danga.com/memcached,
Memcache工作原理
首先 memcached 是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,客户端可以由各种语言编写,目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。客户端在与 memcached 服务建立连接之后,接下来的事情就是存取对象了,每个被存取的对象都有一个唯一的标识符 key,存取操作均通过这个 key 进行,保存到 memcached 中的对象实际上是放置内存中的,并不是保存在 cache 文件中的,这也是为什么 memcached 能够如此高效快速的原因。注意,这些对象并不是持久的,服务停止之后,里边的数据就会丢失。
与许多 cache 工具类似,Memcached 的原理并不复杂。它采用了C/S的模式,在 server 端启动服务进程,在启动时可以指定监听的 ip,自己的端口号,所使用的内存大小等几个关键参数。一旦启动,服务就一直处于可用状态。Memcached 的目前版本是通过C实现,采用了单进程,单线程,异步I/O,基于事件 (event_based) 的服务方式.使用 libevent 作为事件通知实现。多个 Server 可以协同工作,但这些 Server 之间是没有任何通讯联系的,每个 Server 只是对自己的数据进行管理。Client 端通过指定 Server 端的 ip 地址(通过域名应该也可以)。需要缓存的对象或数据是以 key->value 对的形式保存在Server端。key 的值通过 hash 进行转换,根据 hash 值把 value 传递到对应的具体的某个 Server 上。当需要获取对象数据时,也根据 key 进行。首先对 key 进行 hash,通过获得的值可以确定它被保存在了哪台 Server 上,然后再向该 Server 发出请求。Client 端只需要知道保存 hash(key) 的值在哪台服务器上就可以了。
        其实说到底,memcache 的工作就是在专门的机器的内存里维护一张巨大的 hash 表,来存储经常被读写的一些数组与文件,从而极大的提高网站的运行效率。
Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。
  它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。
  为什么会有Memcache和memcached两种名称?
  其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名,
  Memcache官方网站:http://www.danga.com/memcached,
  2       Memcache工作原理
首先 memcached 是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,客户端可以由各种语言编写,目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。客户端在与 memcached 服务建立连接之后,接下来的事情就是存取对象了,每个被存取的对象都有一个唯一的标识符 key,存取操作均通过这个 key 进行,保存到 memcached 中的对象实际上是放置内存中的,并不是保存在 cache 文件中的,这也是为什么 memcached 能够如此高效快速的原因。注意,这些对象并不是持久的,服务停止之后,里边的数据就会丢失。
  与许多 cache 工具类似,Memcached 的原理并不复杂。它采用了C/S的模式,在 server 端启动服务进程,在启动时可以指定监听的 ip,自己的端口号,所使用的内存大小等几个关键参数。一旦启动,服务就一直处于可用状态。Memcached 的目前版本是通过C实现,采用了单进程,单线程,异步I/O,基于事件 (event_based) 的服务方式.使用 libevent 作为事件通知实现。多个 Server 可以协同工作,但这些 Server 之间是没有任何通讯联系的,每个 Server 只是对自己的数据进行管理。Client 端通过指定 Server 端的 ip 地址(通过域名应该也可以)。需要缓存的对象或数据是以 key->value 对的形式保存在Server端。key 的值通过 hash 进行转换,根据 hash 值把 value 传递到对应的具体的某个 Server 上。当需要获取对象数据时,也根据 key 进行。首先对 key 进行 hash,通过获得的值可以确定它被保存在了哪台 Server 上,然后再向该 Server 发出请求。Client 端只需要知道保存 hash(key) 的值在哪台服务器上就可以了。
        其实说到底,memcache 的工作就是在专门的机器的内存里维护一张巨大的 hash 表,来存储经常被读写的一些数组与文件,从而极大的提高网站的运行效率。memcache 可用于java,请看http://www.iteye.com/topic/264010
这里讲php的实现
Memcache的安装
分为两个过程:memcache服务器端的安装和memcached客户端的安装。
所谓服务器端的安装就是在服务器(一般都是linux系统)上安装Memcache实现数据的存储
所谓客户端的安装就是指php(或者其他程序,Memcache还有其他不错的api接口提供)去使用服务器端的Memcache提供的函数,需要php添加扩展。
  具体的配置大家可以参考:
Linux下的Memcache安装:http://www.ccvita.com/257.html
Windows下的Memcache安装:http://www.ccvita.com/258.html
Memcache基础教程:http://www.ccvita.com/259.html
Discuz!的Memcache缓存实现:http://www.ccvita.com/261.html
Memcache协议中文版:http://www.ccvita.com/306.html
Memcache分布式部署方案:http://www.ccvita.com/395.html
  这里说下Memcached的例子

<?php
$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
$version = $memcache->getVersion();
echo "Server's version: ".$version."\n";
$tmp_object = new stdClass;
$tmp_object->str_attr = 'test';
$tmp_object->int_attr = 123;
$memcache->set('key', $tmp_object, false, 10) or die ("Failed to save data at the server");
echo "Store data in the cache (data will expire in 10 seconds)\n";
$get_result = $memcache->get('key');
echo "Data from the cache:\n";
var_dump($get_result);
?>
</pre>
读取的例子
<pre lang='php' line='1'>
<?php
$sql = 'SELECT * FROM users';
$key = md5($sql);   //memcached 对象标识符
if ( !($datas = $mc->get($key)) ) {
//  在 memcached 中未获取到缓存数据,则使用数据库查询获取记录集。
echo "n".str_pad('Read datas from MySQL.', 60, '_')."n";
$conn = mysql_connect('localhost', 'test', 'test');
mysql_select_db('test');
$result = mysql_query($sql);
while ($row = mysql_fetch_object($result))
$datas[] = $row;
//  将数据库中获取到的结果集数据保存到 memcached 中,以供下次访问时使用。
$mc->add($key, $datas);
} else {
echo "n".str_pad('Read datas from memcached.', 60, '_')."n";
}
var_dump($datas);
?>
</pre>

3、静态页面缓存如adodb+smarty实现缓存
<pre lang='php' line='1'>
<?php }
include(./adodb/adodb.inc.php);
$ADODB_CACHE_DIR='tmp';
$db=NewADOConnect('mysql');
$db->connect('localhost','root','123456','mysql');
$sql="select * from user";  
$db->cacheexecute(300,$sql);
?>
</pre>
在temp目录下生产缓存
<pre language='php' line='1'>

?php
require('./smarty/Smarty.class.php');
$smarty = new Smarty; Z)
$smarty->caching = true;
if(!$smarty->is_cached('index.tpl'))  
// No cache available, do variable assignments here. )  
$contents = get_database_contents();
$smarty->assign($contents);
}
$smarty->display('index.tpl'); )
?>

  
还有别的缓存以后再整理

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-355604-1-1.html 上篇帖子: 关于PHP结束标签?>的使用细节 下篇帖子: php 多文件上传类
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表