写一些脚本的心得总结系列第5篇-----文件缓存和静态化
6.改读缓存文件的。
缓存除了memcache和redis这种key-value的存储外,还可以用文件缓存。一般这种方式都适合存一些变化不频繁的小量数据,比如地区表的数据。
原理也很简单,就是读表数据,然后利用var_export到某个文件。
代码如下:
if (file_exists('cache/ad_position.cache.php')) { // 有缓存文件就读取缓存文件 include 'cache/ad_posi.cache.php'; } else { // get data from database $array = $this->mysql->select("select * from ad_posi"); $data = array(); //缓存地区信息。 foreach ($array as $v) { $data[$v['id']] = $v; } $array = var_export($data, true); file_put_contents('cache/ad_posi.cache.php', "<?php return \$data=$array;"); // 写入缓存文件 }
这种直接include进来数据对一些访问量很大的接口或应用效果非常好,但是也有一个问题,就是它是文件,除非被删除,否则没有过期时间,一旦对应的表数据发生变化,它不能及时自动的重新缓存。
后来我在工作中就遇到过这种问题。思路有很多,比如
1.重新写个脚本,每隔一秒去刷一次。
2.开放一个专门的接口,允许手动刷新生成缓存文件。
3.增加一个查询参数,就在原接口上调整。
4.每当ad_posi表发生变化好后自动生成一次缓存文件。
挨个分析一下可行性。第一种是比较费力的笨办法,相当于不断去轮询生成缓存文件,之前我们就说了,这个表作为广告位置表,一般来说一旦入库后改变的概率很小,让一个后台脚本每一秒去刷,有点杀鸡焉用宰牛刀的浪费。
第二种允许单写一个接口手动生成缓存,绝对和现有代码较多重合的地方,虽然让接口保持了单一职责,但是也有吹毛求疵了。
第三种想法ok,改写也简单,只用多传一个标识,判断是否刷新即可。
第四种,是我个人比较喜欢的。原代码不用改一行,只用在可能让ad_posi改变的地方,重新生成一次缓存文件。
但还是要看实际情况中,如果改变该表的地方较多,且在多个不同项目中的话,第四种就显得麻烦了。
最终改为:
$is_update = $this->input->get('is_update'); // 是否更新,true代表是 if (file_exists('cache/ad_position.cache.php') && !$is_update) { // 有缓存文件且不主动更新就直接读取缓存文件 include 'cache/ad_posi.cache.php'; } else { // get data from database $array = $this->mysql->select("select * from ad_posi"); $data = array(); //缓存地区信息。 foreach ($array as $v) { $data[$v['id']] = $v; } $array = var_export($data, true); file_put_contents('cache/ad_posi.cache.php', "<?php return \$data=$array;"); // 写入缓存文件 }
其实全站静态化的原理也是类似,生成好后直接读取静态文件,以此提高页面加载速度。
原理实现如下:
ob_start(); $name = 'freephp'; echo <<<EOT <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>Untitled Document</title> </head> <body> <!--12321--> Hello,$name! </body> </html> EOT; $content = ob_get_contents();//取得php页面输出的全部内容 $fp = fopen("user/show.html", "w"); fwrite($fp, $content); fclose($fp);
利用ob*系列函数来实现输出内容到文件,之后的访问就就是直接读取静态文件了,这对使用vps主机而不能使用redis之类缓存的童鞋,是很好的缓存方式。Smarty(对,好多人都不怎么用它了)也可以做到静态化,而且可以设置那些能缓存,那些部分不缓存。不过有一定学习成本,不如php原生来得粗暴快速。