标签:
从数据库中直接读取数据,虽然时效性很强,但是对数据库造成很大压力,尤其是在高访问量的情况下。这时候可以通过缓存,来有效的缓解了这一压力,虽然时效性有些不足,但是服务器的抗压能力却达到了很大的提高。
读取缓存方式的中心思想:
当请求进来时,先查看是否有缓存,如果有并且缓存还在有效时间内,不再查询数据库,直接返回缓存即可;如果没有或者已经过了有效时间,查询数据库,返回数据,同时生成一份新的缓存,供以后使用。
代码案例,还是在前几天的代码基础上进行改造完善。
File静态缓存类 (原来的代码请参考 http://my.oschina.net/woshixiaomayi/blog/517876)
做了一些修改,将原来cacheData()方法中的第三个参数,由path修改成了cacheTime,用来记录缓存的有效时间。在方法中增加了,写入缓存时间的逻辑,和判断缓存文件是否过期的逻辑,如下:
<?php /******************************** * * 修改File类,cacheData方法中加入了缓存时间参数 * 学php的小蚂蚁 * 原创博客 http://my.oschina.net/woshixiaomayi/blog * ***************************/ class File{ //缓存文件的路径 private $_dir; //缓存文件的默认路径 const EXT=‘.txt‘; //构造方法生成目录 function __construct(){ $this->_dir = dirname(__FILE__).‘/files/‘; if(!is_dir($this->_dir)){ mkdir($this->_dir,0777); } } /************************* * * 缓存文件的生成,修改,删除,第三个参数改成了缓存时间 * $value有值,写入。无值,读出。为null,删除 * @param string $key 文件名 * @param mixed $value 缓存的数据 * @param int $cacheTime 缓存文件的有效时间 * return mixed 返回值为布尔值,字符串,整型 * *******************/ public function cacheData($key,$value=‘‘,$cacheTime=0){ //缓存文件的全路径 $filename = $this->_dir.$key.self::EXT; //如果value为null,这删除这个静态缓存 if(is_null($value)){ return @unlink($filename); } //如果$value不等于空,说明是写入操作 if($value != ‘‘){ //判断提交的path是否存在 $dir = dirname($filename); if(!is_dir($dir)){ mkdir($dir,0777); } /* 在进行写入操作的时候,附带上缓存有效时间 有效时间为11位的整形,不足11位在前端用0补足 这样做方便截取 */ $cacheTime = sprintf(‘%011d‘,$cacheTime); //将缓存有效时间拼接数据json,保存到文件 return file_put_contents($filename,$cacheTime.json_encode($value)); }elseif($value == ‘‘){ //说明是读取操作 if(is_file($filename)){ /* 因为加入了缓存时间,需要将它们拆分开来,进行判断, 缓存是否过期,如果没有过期,返回数据,如果过期了, 删除源文件,返回false。 */ $content=file_get_contents($filename); //拿到本文件的缓存有限时间 $time = (int)substr($content,0,11); /* 进行判断缓存是否可用 1.判断过期时间是不是永久缓存(为0则是永久缓存) 2.缓存时间加上文件修改时间是否小于现在时间,如果小于 则已经过期 */ if($time != 0 && ($time + filemtime($filename) < time())){ //缓存文件不可用,删除该文件,返回false unlink($filename); return false; } //缓存数据可用,拿出数据,直接返回 $value = substr($content,11); return json_decode($value,true); }else{ return false; } } } } ?>
逻辑代码中,需要作出判断,是否存在缓存文件。有并且没有过期,则使用缓存文件,不再读取数据库,没有或者已经过期,则走查询数据库的步骤,同时生成缓存文件。代码中的echo 123,是测试使用,注释已经做出了说明。
<?php /*********************************** * * 读取数据库的方式开发首页接口 * 学php的小蚂蚁 * 博客 http://my.oschina.net/woshixiaomayi/blog * ************************************/ //载入前天写的db类 //代码内容请参考 http://my.oschina.net/woshixiaomayi/blog/518295 require_once(‘./db.php‘); //载入之前写好的接口响应类 //代码内容请参考 http://my.oschina.net/woshixiaomayi/blog/517384 require_once(‘./response.php‘); //载入刚刚改造好的文件静态缓存类 require_once(‘./file.php‘); //接收分页数据 page 为当前第几页 pagesize 一页多少数据 $page = isset($_GET[‘page‘])?$_GET[‘page‘]:1; $pagesize= isset($_GET[‘pagesize‘])?$_GET[‘pagesize‘]:5; //检测这两个数值是否为数字 if(!is_numeric($page) or !is_numeric($pagesize)){ //不是数字,发送错误提示 /* 这里之所以使用了一个return是加强了程序的可读性,因为对程序不熟悉的程序员,不知道 在show方法中有exit,加上一个return,其他人就会知道执行到这一步之后,程序就会停止, 后面的程序就不会执行了。方便了其他人,大家好才是真的好\(^o^)/YES! */ return Response::show(400,‘参数不合法‘); } //设置分页所需要的偏移量 $offset = ($page-1)*$pagesize; //编写sql语句 $sql="select * from ecm_member limit ".$offset.",".$pagesize; //实例化文件缓存类,查看是否存在有效时间内的缓存文件 $file=new File(); if(!$index_data=$file->cacheData(‘list‘.$page.‘_‘.$pagesize)){ /* 此处为调试,在第一次访问的时候,echo 的123可以出现,之后访问,由于 已经生成缓存,则不再走这一步,所以123不会出现。直到有效时间过去,才会 再次出现 */ echo 123; //如果连接数据库的时候出错,获取信息,并将自定义的信息返回 //以免将错误直接暴露给用户 try{ $connect = Db::getInstance()->connect(); }catch(Exception $e){ //返回给APP的错误提示 return Response::show(400,‘mysql not connect‘); } //数据库连接成功,执行sql语句,获取结果集 $result = mysql_query($sql,$connect); $index_data=array(); while($row=mysql_fetch_assoc($result)){ $index_data[]=$row; } $file->cacheData(‘list‘.$page.‘_‘.$pagesize,$index_data,15); } if($index_data){ //所需的结果数据拿到,返回数据 return Response::show(200,‘内容获取成功‘,$index_data); }else{ //没有拿到,返回错误提示 return Response::show(400,‘首页数据获取失败‘); } ?>
读取缓存方式开发接口的思想基本上就是这样了,很好理解,不过这里用了一个最笨的方法,在本地保存文件的形式做了缓存,其实可以使用一些更高级的服务,例如memcache、redis等进行缓存,效率更高,有时间的话,使用这两种服务再测试一下 ~(~ ̄▽ ̄)~ 加了个油。
小蚂蚁学习APP接口开发(7)—— APP接口实例——读取缓存方式开发APP接口的代码案例
标签:
原文地址:http://my.oschina.net/woshixiaomayi/blog/518885