検索
ホームページバックエンド開発PHPチュートリアルphp多用户读写文件冲突的解决办法_PHP

php多用户读写文件冲突的解决办法_PHP

Jun 01, 2016 am 11:58 AM
php ファイルの読み取りと書き込み

一般的方案会是:
复制代码 代码如下:
$fp = fopen("/tmp/lock.txt", "w+");
if (flock($fp, LOCK_EX)) {
    fwrite($fp, "Write something heren");
    flock($fp, LOCK_UN);
} else {
    echo "Couldn't lock the file !";
}
fclose($fp);

但在PHP中,flock似乎工作的不是那么好!在多并发情况下,似乎是经常独占资源,不即时释放,或者是根本不释放,造成死锁,从而使服务器的cpu占用很高,甚至有时候会让服务器彻底死掉。好像在很多linux/unix系统中,都会有这样的情况发生。
所以使用flock之前,一定要慎重考虑。
那么就没有解决方案了吗?其实也不是这样的。如果flock()我们使用得当,完全可能解决死锁的问题。当然如果不考虑使用flock()函数,也同样会有很好的解决方案来解决我们的问题。
经过我个人的搜集和总结,大致归纳了解决方案有如下几种。
方案一:对文件进行加锁时,设置一个超时时间.
大致实现如下:
复制代码 代码如下:
if($fp = fopen($fileName, 'a')) {
 $startTime = microtime();
 do {
         $canWrite = flock($fp, LOCK_EX);
  if(!$canWrite) usleep(round(rand(0, 100)*1000));
 } while ((!$canWrite)&& ((microtime()-$startTime)  if ($canWrite) {
   fwrite($fp, $dataToSave);
 }
 fclose($fp);
}
 
超时设置为1ms,如果这里时间内没有获得锁,就反复获得,直接获得到对文件操作权为止,当然。如果超时限制已到,就必需马上退出,让出锁让其它进程来进行操作。
方案二:不使用flock函数,借用临时文件来解决读写冲突的问题。
大致原理如下:
1。将需要更新的文件考虑一份到我们的临时文件目录,将文件最后修改时间保存到一个变量,并为这个临时文件取一个随机的,不容易重复的文件名。
2。当对这个临时文件进行更新后,再检测原文件的最后更新时间和先前所保存的时间是否一致。
3。如果最后一次修改时间一致,就将所修改的临时文件重命名到原文件,为了确保文件状态同步更新,所以需要清除一下文件状态。
4。但是,如果最后一次修改时间和先前所保存的一致,这说明在这期间,原文件已经被修改过,这时,需要把临时文件删除,然后返回false,说明文件这时有其它进程在进行操作。
大致实现代码如下:
复制代码 代码如下:
$dir_fileopen = "tmp";

function randomid() {
    return time().substr(md5(microtime()), 0, rand(5, 12));
}
function cfopen($filename, $mode) {
    global $dir_fileopen;
    clearstatcache();
    do {
        $id = md5(randomid(rand(), TRUE));
        $tempfilename = $dir_fileopen."/".$id.md5($filename);
    } while(file_exists($tempfilename));
    if (file_exists($filename)) {
        $newfile = false;
        copy($filename, $tempfilename);
    }else{
        $newfile = true;
    }
    $fp = fopen($tempfilename, $mode);
    return $fp ? array($fp, $filename, $id, @filemtime($filename)) : false;
}
function cfwrite($fp,$string) { return fwrite($fp[0], $string); }
function cfclose($fp, $debug = "off") {
    global $dir_fileopen;
    $success = fclose($fp[0]);
    clearstatcache();
    $tempfilename = $dir_fileopen."/".$fp[2].md5($fp[1]);
    if ((@filemtime($fp[1]) == $fp[3]) || ($fp[4]==true && !file_exists($fp[1])) || $fp[5]==true) {
        rename($tempfilename, $fp[1]);
    }else{
        unlink($tempfilename);
  //说明有其它进程 在操作目标文件,当前进程被拒绝
        $success = false;
    }
    return $success;
}
$fp = cfopen('lock.txt','a+');
cfwrite($fp,"welcome to beijing.n");
fclose($fp,'on');
 

对于上面的代码所使用的函数,需要说明一下:
1.rename();重命名一个文件或一个目录,该函数其实更像linux里的mv。更新文件或者目录的路径或名字很方便。
但当我在window测试上面代码时,如果新文件名已经存在,会给出一个notice,说当前文件已经存在。但在linux下工作的很好。
2.clearstatcache();清除文件的状态.php将缓存所有文件属性信息,以提供更高的性能,但有时,多进程在对文件进行删除或者更新操作时,php没来得及更新缓存里的文件属性,容易导致访问到最后更新时间不是真实的数据。所以这里需要使用该函数对已保存的缓存进行清除。
方案三:对操作的文件进行随机读写,以降低并发的可能性。
在对用户访问日志进行记录时,这种方案似乎被采用的比较多。
先前需要定义一个随机空间,空间越大,并发的的可能性就越小,这里假设随机读写空间为[1-500],那么我们的日志文件的分布就为log1~到log500不等。每一次用户访问,都将数据随机写到log1~log500之间的任一文件。
在同一时刻,有2个进程进行记录日志,A进程可能是更新的log32文件,而B进程呢?则此时更新的可能就为log399.要知道,如果要让B进程也操作log32,概率基本上为1/500,差不多约等于零。
在需要对访问日志进行分析时,这里我们只需要先将这些日志合并,再进行分析即可。
使用这种方案来记录日志的一个好处时,进程操作排队的可能性比较小,可以使进程很迅速的完成每一次操作。
方案四:将所有要操作的进程放入一个队列中。然后专门放一个服务完成文件操作。
队列中的每一个排除的进程相当于第一个具体的操作,所以第一次我们的服务只需要从队列中取得相当于具体操作事项就可以了,如果这里还有大量的文件操作进程,没关系,排到我们的队列后面即可,只要愿意排,队列的多长都没关系。
对于以前几种方案,各有各的好处!大致可能归纳为两类:
1、需要排队(影响慢)比如方案一、二、四
2、不需要排队。(影响快)方案三
在设计缓存系统时,一般我们不会采用方案三。因为方案三的分析程序和写入程序是不同步的,在写的时间,完全不考虑到时候分析的难度,只管写的行了。试想一下,如我们在更新一个缓存时,如果也采用随机文件读写法,那么在读缓存时似乎会增加很多流程。但采取方案一、二就完全不一样,虽然写的时间需要等待(当获取锁不成功时,会反复获取),但读文件是很方便的。添加缓存的目的就是要减少数据读取瓶颈,从而提高系统性能。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
PHPメール:ステップバイステップ送信ガイドPHPメール:ステップバイステップ送信ガイドMay 09, 2025 am 12:14 AM

PhpisusedForsedingEmailsDueToitsIttegration withServerMailServicesAndExternalSmtpproviders、自動化とMarketingCampaign.1)SetupYourphpenvironment withebeBironment witheBiserverandphp、保証

PHP経由で電子メールを送信する方法:例とコードPHP経由で電子メールを送信する方法:例とコードMay 09, 2025 am 12:13 AM

メールを送信する最良の方法は、PHPMailerライブラリを使用することです。 1)Mail()関数を使用することはシンプルですが信頼できないため、電子メールがスパムを入力するか、配信できない場合があります。 2)PHPMailerは、より良い制御と信頼性を提供し、HTMLメール、添付ファイル、SMTP認証をサポートします。 3)SMTP設定が正しく構成されていることを確認し、暗号化(StartTLSやSSL/TLSなど)を使用してセキュリティを強化します。 4)大量の電子メールについては、メールキューシステムを使用してパフォーマンスを最適化することを検討してください。

高度なPHPメール:カスタムヘッダーと機能高度なPHPメール:カスタムヘッダーと機能May 09, 2025 am 12:13 AM

customedersandaddadvancedfeaturesinphpemailentalitylivainability.1)customederadddetadata fortrackingandcategorization.2)htmLemailsallowStingtintintintintintinteractivity.3)添付物質の添付物質の添付

php&smtpでメールを送信するためのガイドphp&smtpでメールを送信するためのガイドMay 09, 2025 am 12:06 AM

PHPとSMTPを使用してメールを送信することは、PHPMailerライブラリを介して実現できます。 1)PHPMailerをインストールして構成する、2)SMTPサーバーの詳細を設定する、3)電子メールコンテンツを定義し、4)メールを送信してエラーを処理します。この方法を使用して、電子メールの信頼性とセキュリティを確保します。

PHPを使用して電子メールを送信する最良の方法は何ですか?PHPを使用して電子メールを送信する最良の方法は何ですか?May 08, 2025 am 12:21 AM

BestappRoachforseminginphpisusingthephpmailerlibrarydueToitsReliability、featurrichness、andeaseofuse.phpmailerSupportssmtpは、detairederorhandlingを提供します

PHPでの依存関係注射のベストプラクティスPHPでの依存関係注射のベストプラクティスMay 08, 2025 am 12:21 AM

依存関係注射(DI)を使用する理由は、コードのゆるい結合、テスト可能性、および保守性を促進するためです。 1)コンストラクターを使用して依存関係を注入します。2)サービスロケーターの使用を避け、3)依存関係噴射コンテナを使用して依存関係を管理する、4)依存関係を注入することでテスト可能性を向上させる、5)注入依存性を回避、6)パフォーマンスに対するDIの影響を考慮します。

PHPパフォーマンスのチューニングのヒントとコツPHPパフォーマンスのチューニングのヒントとコツMay 08, 2025 am 12:20 AM

phpperformancetuningisucial cuseenhancess andandandadsand。

PHP電子メールセキュリティ:電子メールを送信するためのベストプラクティスPHP電子メールセキュリティ:電子メールを送信するためのベストプラクティスMay 08, 2025 am 12:16 AM

bestpracticesforsendingemails securlyinphpinclude:1)sutureconsmttarttlsencryptionとの使用の使用、2)検証およびサンシジン化のinputStopReventinjectuctacks、3)adinitivedinitivedInemailsopenslsl、4)adlinglinglingemailoaに

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール