写一些脚本的心得总结系列第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原生来得粗暴快速。

原文地址:https://www.cnblogs.com/freephp/p/5094744.html