2011-12-20 17 views
1

私は単純なデータベース駆動のPHPウェブサイトを作った。今私はサイトにいくつかの簡単なキャッシングを実装しようとしています。私はどこかでこれを試しましたシンプルなPHPキャッシングでのファイル書き込み中のエラー

<?php 
     $reqfilename="test"; 
     $cachetime = 60*5; // 5 minutes 
     $cachefile = "cache/".$reqfilename.".html"; 
     $cf2="cache/".$reqfilename."2.html"; 
     if (file_exists($cachefile) && ((time() - $cachetime) < filemtime($cachefile))) 
     { 
     include($cachefile); 
     exit; 
     } 
     ob_start(); 
?> 
CONTENT OF THE PAGE GOES HERE 
<?php 
     $fp = @fopen($cf2, 'w'); 
     if($fp){ 
      fwrite($fp, ob_get_contents()); 
      fclose($fp); 
      rename($cf2,$cachefile); 
     } 
     ob_end_flush(); 
?> 

しかし、キャッシュファイルの名前が変更され、誰かがページを要求した場合はどうなりますか?エラーが表示されるのでしょうか、またはユーザーに遅延が発生しますか?この(以下webbiedaveによって回答に基づいて)を行うための正しいコードをのみ、私は名前を変更使用しています直接ではなく、元のキャッシュファイルに

を書いて変更されたキャッシュファイルの時間を短縮する

<?php 
     $reqfilename="test"; 
     $cachetime = 60*5; // 5 minutes 
     $cachefile = "cache/".$reqfilename.".html"; 

     if (file_exists($cachefile) && ((time() - $cachetime) < filemtime($cachefile))) 
     { 
     include($cachefile); 
     exit; 
     } 
     ob_start(); 
?> 
CONTENT OF THE PAGE GOES HERE 
<?php 
     $fp = @fopen($cachefile, 'w'); 
    if (flock($fp, LOCK_EX | LOCK_NB)) { 
    fwrite($fp, ob_get_contents()); 
    flock($fp, LOCK_UN); 
    fclose($fp); 
    } 

    ob_end_flush(); ?> 

答えて

1

が問題の原因ではありません正しく、ソースが動作するとは思いません。あなたのスクリプトの主な競合条件は、期限切れのmtimeを検出する複数の要求とすべての書き込みをtest2.htmlにすることです。

有効な方法は、期限切れのmtimeを検出した直後に、非ブロックの排他的な非ブロックを実行し、出力をバッファし、ファイルを上書きしてロックを解除することです。 flockがfalseを返すと、別のプロセスが書き込みを行い、現在のプロセスは書き込みを完全にスキップする必要があります。

ロック中にリクエストが行われた場合、Webサーバーはファイルの書き込みが完了するまで待機してロックを解除し、ファイルを提供します。

+0

ありがとうございました。私が探していたことがまさにそれです。以前はLOCK_NBを考えていませんでした。再度、感謝します。 – PRYM

0

あなたは、キャッシュファイルを削除しないので、私は、ファイルの名前を変更

+0

なぜキャッシュファイルを削除する必要がありますか?ファイルは、ページを表示するために使用されるファイルとして名前が変更されています。 – PRYM

関連する問題