使用etag和文件缓存降低服务器数据库压力-PHP源码
使用php5.3+,使用了一些自定义的内容,不过都一看便知
比如常量ROOT、DIR_CACHE等
核心使用的有
diehere(输出json字符串,并die),err_a(组合错误信息),makedir(连续创建目录)
其余的都根据实际使用的情况来
终于debug完成了……新增one_key方法,一键完成输出,完美……
departments初次查询170ms
之后仅16ms,越复杂效果越好啊
高复杂测试get_users_complex.php
初次108.0 KB 985ms
第二次16ms,哈哈哈,
清空etag(未清空data)读取,接收数据125ms
1. [代码]DEF.inc.php
define('ROOT',dirname(__FILE__)); define('CLS_SCACHER','/inc/SCACHER.cls.php'); define('CLS_ECACHER','/inc/ECACHER.cls.php'); define('DIR_CACHE','/cache/'); //用于缓存判断的目录 function run_sql($sql){ static $db; if(!$db){ $db=getdb(); } return mysql_query($sql,$db); } function getdb(){ static $mydb; if(!$mydb){ $mydb=dbconnection(); } return $mydb; } function dbconnection(&$var=0){ if($var==0||!is_array($var)){$var=array();} if(!isset($var['dbhost']) || !is_string($var['dbhost'])){ $var['dbhost']=constant('DBHOST');} if(!isset($var['dbuser']) || !is_string($var['dbuser'])){ $var['dbuser']=constant('DBUSER');} if(!isset($var['dbpsw']) || !is_string($var['dbpsw'])){$var['dbpsw']=constant('DBPSW');} $db=mysql_connect($var['dbhost'],$var['dbuser'],$var['dbpsw']) or die(); if(!$db){return 0;} mysql_select_db(constant('DBNAME'),$db) or die();//echo('db enter here'); mysql_query("SET NAMES 'UTF8'"); return $db; } function PR($v){ if(isset($v)){ echo(''); print_r($v); echo(''); } } function rs_2_array($rs){ //this is a function used to make the code clear and less //i am tired to code same code to get the arry result //thought it is not much //redlz2500@2008-06-24 $t=array(); try { while($row=mysql_fetch_array($rs,MYSQL_ASSOC)){ $t[]=$row; } return $t; }catch (Exception $e) { } return $t; } /* * 功能:连续建目录 * $dir 目录字符串 */ function makedir($dir,$mode = '0777') { //notice: the $dir will not set the code style & //as maybe call by $str.$str1 //the var can not be reference if(!isset($dir)){return 0;} //echo('
**********intomakedir*************
'.$dir); $dir = str_replace( "\\", "/", $dir ); $mdir = ""; foreach( explode( "/", $dir ) as $val ) { $mdir .= $val."/"; if( $val == ".." || $val == "." ) continue; if( ! file_exists( $mdir ) ) { if(!@mkdir( $mdir, $mode )){ echo "创建目录 [".$mdir."]失败."; exit; } } } return true; }
2. [代码]CLS_SCACHER
scacher($opt); } public function scacher($opt=[]){ $flag=false; if($opt['category'] && is_string($opt['category']) && ($this->category!=$opt['category']) ){ $this->category=$opt['category']; $flag=true; } if($opt['name'] && is_string($opt['name']) && ($this->name!=$opt['name'])){ $this->name=$opt['name']; $flag=true; } if($opt['path'] && is_string($opt['path']) && ($this->pat!=$opt['path'])){ $this->path=$opt['path']; $flag=true; } if($flag){ if($this->path){ $this->fullpath=ROOT.DIR_CACHE.$this->path.'/'; }else{ $this->fullpath=ROOT.DIR_CACHE; } if(!file_exists($this->fullpath)){ makedir($this->fullpath); if(!file_exists($this->fullpath)){ throw new Exception('errSCACHER配置失败 当前调用参数:'.$this->category.'.'.$this->name); } } } } public function set($v){ $fp=fopen($this->fullpath . $this->category .'.'. $this->name,'w'); if (!fwrite($fp,$v)) { return ['success'=>false,'error'=>err_a('errSCACHER_1','数据写入失败,请稍后重试。
重试无效请联系管理员。
当前调用参数:'.$this->category.'.'.$this->name)]; } @fclose($fp); return ['success'=>true]; } public function get(){ $f=$this->fullpath . $this->category .'.'. $this->name; if(file_exists($f)){ $res=@file_get_contents($f); if(!$res){ $res=''; } return ['success'=>true,'data'=>$res]; }else{ return ['success'=>false,'data'=>'','error'=>err_a('errSCACHER_3','未找到缓存。
当前调用参数:'.$this->category.'.'.$this->name)]; } } public function del(){ $f=$this->fullpath . $this->category .'.'. $this->name; if(file_exists($f)){ @unlink($f); if(file_exists($f)){ return ['success'=>false,'error'=>err_a('errSCACHER_2','数据处理异常,请稍后重试。
重试无效请联系管理员。
当前调用参数:'.$this->category.'.'.$this->name)]; } }else{ return ['success'=>true]; } } } ?>
3. [代码]CLS_ECACHER
scacher=new scacher([]); //scacher实例,路径由scacher来控制 $this->ecacher($opt); } public function __destruct(){ } function ecacher($opt){ if(is_array($opt)){ if($opt['force_cache']){ $this->force_cache=true; }else{ if(isset($opt['force_cache'])){ $this->force_cache=false; } } if($opt['path'] && is_string($opt['path'])){ $this->path=$opt['path']; } if($opt['category'] && is_string($opt['category'])){ $this->category=$opt['category']; } if($opt['name'] && is_string($opt['name'])){ $this->name=$opt['name']; } if(isset($opt['auto_send_etag_header'])){ $this->auto_send_etag_header=$opt['auto_send_etag_header']; } if($opt['create_fn'] && is_string($opt['create_fn'])){ $this->create_fn=$opt['create_fn']; } if($opt['create_par']){ if(is_array($opt['create_par'])){ $this->create_par=$opt['create_par']; }else{ $this->create_par=[$opt['create_par']]; } }else{ $this->create_par=[]; } $this->scacher->scacher($opt);//更新的数据写入(好吧,其实并没有什么卵用)(好吧,可以提前判断缓存路径有没有效) } } private function mode_etag(){ $this->scacher->scacher(['name'=>$this->name.'.etag']); } private function mode_data(){ $this->scacher->scacher(['name'=>$this->name.'.']); } public function etag_chk(){ $this->mode_etag();//设置etag模式 $etag=$this->scacher->get(); echo_debug('test etag'); echo_debug($etag); if($etag['success']){ $etag=$etag['data']; }else{ return $etag; } $s_etag=$_SERVER['HTTP_IF_NONE_MATCH']; echo_debug('etag from browse'); echo_debug($s_etag); if($etag){ if($s_etag==$etag){ if($this->auto_send_etag_header){ if($this->force_cache){ header('Cache-Control: max-age=0'); header('Expires: '.gmdate('D, d M Y H:i:s', time() + SERVER_TIME_SHIFT + 10 ) . ' GMT' ); } header('Etag:'.$etag,true,304); die();//必须die,否则还会继续执行下去。 }else{ return [ 'etag'=>$etag, 'statue'=>DEF_ECACHE_PERFECT ]; } }else{ if($this->auto_send_etag_header){ if($this->force_cache){ header('Cache-Control: max-age=0'); header('Expires: '.gmdate('D, d M Y H:i:s', time() + SERVER_TIME_SHIFT + 10 ) . ' GMT' ); } header('Etag:'.$etag); } return [ 'etag'=>$etag, 'statue'=>DEF_ECACHE_BROWSER_NULL ]; } }else{ return [ 'etag'=>'', 'statue'=>DEF_ECACHE_ETAG_NULL ]; } } public function etag_create($auto=false){ $etag=md5($this->category.':'.$this->name.':'.time().':'.ranstr()); $this->mode_etag(); $this->scacher->set($etag); if($auto){ if($this->force_cache){ header('Cache-Control: max-age=0'); header('Expires: '.gmdate('D, d M Y H:i:s', time() + SERVER_TIME_SHIFT + 10 ) . ' GMT' ); } header('Etag:'.$etag); } echo_debug('etag create finish:'.$etag); return [ 'success'=>true, 'etag'=>$etag, 'status'=>DEF_ECACHE_ETAG_CREATED ]; } public function data_get(){ //PR('begin get data');BR(); $this->mode_data(); $data=$this->scacher->get(); if($data['success']){ echo_debug('orgin data is:'); echo_debug($data['data']); $data['data']=unserialize($data['data']); }else{ echo_debug('not success:'); echo_debug($data); $data['data']=''; } echo_debug(); echo_debug('the data is:'); echo_debug($data); return $data; } public function data_create($auto_etag=false){ if(!$this->create_fn){ throw new Exception('未传递数据生成函数
当前参数:'.$this->category.'.'.$this->name); //这样的错误时不允许的,因此直接抛出错误 die(); } $data=call_user_func_array($this->create_fn,$this->create_par); //生成数据的处理 if($data===false){ throw new Exception('生成数据失败
当前参数:'.$this->category.'.'.$this->name); //无法,只有不返回false了 die(); } //PR($data); $s_data=serialize($data); $this->mode_data(); $res=$this->scacher->set($s_data); if(!$res['success']){ return $res; } if($auto_etag){ $res=$this->etag_create(); if(!$res['success']){ return $res; } } return ['success'=>true,'data'=>$data]; } public function clear($p=['etag','data']){ if(in_array('both',$p)){ $p=['etag','data']; } if(in_array('etag',$p)){ $this->mode_data(); $res=$this->scacher->del(); if(!$res['success']){ return $res; } } if(in_array('etag',$p)){ $this->mode_etag(); $res=$this->scacher->del(); if(!$res['success']){ return $res; } } return ['success'=>true]; } public function one_key(){ $r=$this->etag_chk(); if(!$r['etag']){ echo_debug('the etag is null,should be rebuild'); echo_debug($r); $this->etag_create('auto'); } $res=$this->data_get(); if($res['success']){ //PR($res); if($res['data']){ diehere($res); } } echo_debug('recreate data'); $data=$this->data_create(); diehere($data); } } ?>
4. [代码]get_departments.php
'get_departments', 'path'=>'json','category'=>'common','name'=>'department' ]); $e->one_key(); die(); function get_departments(){ $sql='select `depid` as `id`,`name`,`father`,`departcode` as `code` from `department` where `father` !=0'; $rs=run_sql($sql); $data=[]; require_once(ROOT.INC_MAIL); while($row=mysql_geta($rs)){ $address=get_dep_mail_address($row['id']); $fullname=explode('.',$address); $fullname=array_reverse($fullname); $fullname=implode('.',$fullname); $row['fullname']=$fullname; $data[]=$row; } return $data; } ?>
5. [代码]get_users.php
'get_users', 'create_par'=>$par['depid'], 'path'=>'json','category'=>'common','name'=>'users_in_'.$par['depid']]); $e->one_key(); function get_users($depid){ $sql='select `uid`,`name`,`login`,`depid` from `user` where `register` = 1 and `depid` = '.$depid; $rs=run_sql($sql); $rs=rs_2_array($rs); return $rs; } ?>
6. [代码]get_users_complex.php
'get_users', 'create_par'=>$par['depid'], 'path'=>'json','category'=>'common','name'=>'users_all']); $e->one_key(); function get_users(){ $sql='select `uid`,`name`,`login`,`depid` from `user` where `register` = 1 '; $rs=run_sql($sql); require_once(ROOT.INC_MAIL); $data=[]; while($row=mysql_geta($rs)){ $addr=_get_user_mail_address($row['login']); $row['addr']=$addr; $data[]=$row; } return $data; } ?>
PHP之友评论