PHP共通キャッシュ技術分析(cache)


ほとんどの場合、私たちのウェブサイトでは、サイトデータが格納されているコンテナとしてデータベースが使用されます.SQLクエリーを実行する場合、典型的な処理手順は、データベースの接続->SQLクエリーの準備->データベースへのクエリーの送信->データベースの戻り結果の取得->データベース接続のクローズです.しかし、データベースの一部のデータは完全に静的またはあまり頻繁に変動しないため、キャッシュシステムはSQLクエリーの結果をより速いストレージシステムにキャッシュすることで、データベースの頻繁な操作を避けることでプログラムの実行時間を大幅に向上させ、キャッシュクエリーの結果も後期処理を許可します.
一般的に使用されているキャッシュ・テクノロジー
≪データ・キャッシュ|Data Cache|emdw≫:ここでいうデータ・キャッシュとは、データベース・クエリー・キャッシュのことです.ページにアクセスするたびに、対応するキャッシュ・データが存在するかどうかを検出し、存在しない場合はデータベースに接続してデータを取得し、クエリー結果をシーケンス化してファイルに保存します.その後、同じクエリー結果がキャッシュ・ファイルから直接取得されます.
ページキャッシュ:
ページにアクセスするたびに、対応するキャッシュページファイルが存在するかどうかを検出し、存在しない場合はデータベースに接続し、データを取得し、ページを表示しながらキャッシュページファイルを生成することで、次回アクセスするときにページファイルが機能します.(テンプレートエンジンやネット上でよく見られるキャッシュクラスには、通常この機能があります)
メモリキャッシュ:
ここでは紹介しないで、本文で議論するのではなく、簡単に述べるだけです.
Memcachedは高性能で、分散型のメモリオブジェクトキャッシュシステムで、動的アプリケーションでデータベース負荷を低減し、アクセス速度を向上させる.
dbcachedはMemcachedとNMDBに基づく分散key-valueデータベースメモリキャッシュシステムです.
以上のキャッシュ・テクノロジーは、頻繁にデータベースをクエリーする問題をうまく解決できますが、データの非時効性が欠点です.次に、プロジェクトでよく使用する方法を示します.
タイムトリガキャッシュ:
ファイルが存在し、タイムスタンプが設定された有効期限より小さいかどうかを確認します.ファイルが変更したタイムスタンプが現在のタイムスタンプから有効期限を減算したタイムスタンプより大きい場合は、キャッシュを使用します.そうしないと、キャッシュが更新されます.
設定時間内にデータが更新されるか否かを判断せず、設定時間を過ぎてからキャッシュを更新する.以上は、時効性に対する要求が高くない場合にのみ適用されます.そうでなければ、以下を参照してください.
コンテンツトリガキャッシュ:
データを挿入したり更新したりすると、キャッシュが強制的に更新されます.
ここでは、大量のデータが頻繁に更新される場合、最後にディスクの読み書き操作に関連することがわかります.どうやって解決しますか?私は日常プロジェクトでは、通常、すべてのコンテンツをキャッシュするのではなく、頻繁に変化しないコンテンツの一部をキャッシュして解決します.ただし、大きな負荷の場合は、共有メモリをキャッシュシステムとして使用することが望ましい.
ここまでPHPキャッシュは少し解決策があるかもしれませんが、その欠点は、リクエストごとにPHP解析が行われるため、大負荷の場合は効率の問題が効果よりも深刻であるため、この場合は静的キャッシュが使用される可能性があります.
静的キャッシュ
ここでいうスタティックキャッシュとはHTMLキャッシュのことで、HTMLキャッシュは一般的にデータが更新されるかどうかを判断する必要はありません.通常、HTMLを使用する場合、内容を頻繁に変更しないページが多いからです.データ更新の際にHTMLも強制的に更新すればいいです.
 
 
 
 
例1:
 
 
cacheCheck();
 
echo date("Y-m-d H:i:s");
 
$cache->caching();
*/
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;
  }
}


$cache = new cache(30);
$cache->cacheCheck();
 
echo date("Y-m-d H:i:s");
 
$cache->caching();

?>
 
 
インスタンス2:データ・キャッシュ
 
dir = $dir; }
    }

    private function _name($key)
    {
        return sprintf("%s/%s", $this->dir, sha1($key));
    }

    public function get($key, $expiration = '')
    {

        if ( !is_dir($this->dir) OR !is_writable($this->dir))
        {
            return FALSE;
        }

        $cache_path = $this->_name($key);

        if (!@file_exists($cache_path))
        {
            return FALSE;
        }

		$expiration = empty($expiration) ? $this->expiration : $expiration;

        if (filemtime($cache_path) < (time() - $expiration))
        {
            $this->clear($key);
            return FALSE;
        }

        if (!$fp = @fopen($cache_path, 'rb'))
        {
            return FALSE;
        }

        flock($fp, LOCK_SH);

        $cache = '';

        if (filesize($cache_path) > 0)
        {
            $cache = unserialize(fread($fp, filesize($cache_path)));
        }
        else
        {
            $cache = NULL;
        }

        flock($fp, LOCK_UN);
        fclose($fp);

        return $cache;
    }

    public function set($key, $data)
    {

        if ( !is_dir($this->dir) OR !is_writable($this->dir))
        {
             $this->_makeDir($this->dir);
        }

        $cache_path = $this->_name($key);

        if ( ! $fp = fopen($cache_path, 'wb'))
        {
            return FALSE;
        }

        if (flock($fp, LOCK_EX))
        {
            fwrite($fp, serialize($data));
            flock($fp, LOCK_UN);
        }
        else
        {
            return FALSE;
        }
        fclose($fp);
        @chmod($cache_path, 0777);
        return TRUE;
    }

    public function clear($key)
    {
        $cache_path = $this->_name($key);

        if (file_exists($cache_path))
        {
            unlink($cache_path);
            return TRUE;
        }

        return FALSE;
    }

    public function clearAll()
    {
		$dir = $this->dir;
		if (is_dir($dir)) 
		{
			$dh=opendir($dir);

			while (false !== ( $file = readdir ($dh))) 
			{

				if($file!="." && $file!="..") 
				{ 
					$fullpath=$dir."/".$file;
					if(!is_dir($fullpath)) {
						unlink($fullpath);
					} else {
						delfile($fullpath);
					}
				}
			}
			closedir($dh);
			// rmdir($dir);
		}
  }

   private 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;
	}
}
 
例:
 

require_once('cache.php');

$cache = new Cache();

$data = $cache->get('key');

if ($data === FALSE)
{
    $data = 'This will be cached';
    $cache->set('key', $data);
	echo $data.'--first time';
}
	
echo $data;

//$cache->clearAll();
//$cache->clear('key');

//Do something with $data
 
 
別のデータ・キャッシュ:
 
root_dir = $root_dir;
        
        if (FALSE == file_exists($this->root_dir))
        {
            mkdir($this->root_dir, 0700, true);
        }
    }
    
    public function set ($key, $value)
    {
        $key = $this->escape_key($key);
        
        $file_name = $this->root_dir . '/' . $key;
        
        $dir = dirname($file_name);
        
        if (FALSE == file_exists($dir))
        {
            mkdir($dir, 0700, true);
        }
        
        file_put_contents($file_name, serialize($value), LOCK_EX);
    }
    
    public function get ($key)
    {
        $key = $this->escape_key($key);
        
        $file_name = $this->root_dir . '/' . $key;
        
        if (file_exists($file_name))
        {
            return unserialize(file_get_contents($file_name));
        }
        
        return null;
    }
    
    public function remove ($key)
    {
        $key = $this->escape_key($key);
        
        $file = $this->root_dir . '/' . $key;
        
        if (file_exists($file))
        {
            unlink($file);
        }
    }
    
    public function remove_by_search ($key)
    {
        $key = $this->escape_key($key);
        
        $dir = $this->root_dir . '/' . $key;
        
        if (strrpos($key, '/') < 0)
            $key .= '/';
        
        if (file_exists($dir))
        {
            $this->removeDir($dir);
        }
    }
    
    private function escape_key ($key)
    {
        return str_replace('..', '', $key);
    }
    
    function removeDir($dirName)
    {
        $result = false;
        
        $handle = opendir($dirName);
        
        while(($file = readdir($handle)) !== false)
        {
            if($file != '.' && $file != '..')
            {
                $dir = $dirName . DIRECTORY_SEPARATOR . $file;
            
                is_dir($dir) ? $this->removeDir($dir) : unlink($dir);
            }
        }
        
        closedir($handle);
        
        rmdir($dirName) ? true : false;
        
        return $result;
    }
}


$data_1 = array(
  'u_id' => 1,
  'name' => '  '
);

$data_2 = array(
  'u_id' => 2,
  'name' => 'WaWa'
);

$cache = new file_cache("test");

$cache->set("user/1/data", $data_1);  //    
$cache->set("user/2/data", $data_2);  //    

$result = $cache->get("user/1/data"); //    

echo '    :
';
print_r($result);

//$cache->remove("user/1/data"); //    

//$cache->remove_by_search("user", $data_1);  //  user       
 
 
 
 
 
2つの れた のキャッシュクラスを