検索
ホームページバックエンド開発PHPチュートリアルPHP でのファイルの同時読み取りと書き込みの競合の問題を解決する

毎日の IP が高くないか、同時実行数がそれほど多くないアプリケーションの場合は、通常、これらを考慮する必要はありません。通常のファイル操作方法では全く問題ありません。しかし、同時実行性が高い場合、ファイルの読み取りと書き込みを行うときに、ファイルへのアクセスがそれに応じて独占されないと、複数のプロセスが次のファイルに対して動作する可能性が高くなります。例: オンライン チャット ルーム (チャットの内容がファイルに書き込まれるものとします) では、ユーザー A とユーザー B の両方が同時にデータ保存ファイルを操作する必要があります。まず、A がファイルを開き、次にファイルを開きます。はその中のデータを更新しますが、ここでは B も同じファイルが開かれ、その中のデータが更新されようとしていました。 A が書き込んだファイルを保存すると、実際には B がそのファイルを開いていることになります。しかし、B がファイルを保存し直すと、すでにデータ損失が発生しています。ユーザー B は、変更したときに開いたファイルを知らないため、ユーザー A もファイルを変更したため、最終的にユーザー B が変更を保存するときに、ユーザーA の更新は失われます。このような問題に対する一般的な解決策は、あるプロセスがファイルを操作するときに、まず他のプロセスをロックすることです。つまり、このプロセスだけがファイルを読み取る権利を持ち、他のプロセスが現在読み取っている場合には問題はありません。ただし、この時点でプロセスがファイルを更新しようとすると、その操作は拒否され、以前にファイルをロックしていたプロセスがファイルの更新操作を完了すると、排他的識別子が解放され、ファイルが復元されます。 . 変更可能な状態に達しました。次に、同様に、プロセスがファイルを操作するときにファイルがロックされていない場合は、ファイルを安全にロックして単独で楽しむことができます。したがって、一般的な解決策は次のようになります:

<p>$fp=fopen('/tmp/lock.txt','w+');</p>if (flock($fp,LOCK_EX)){<br />    fwrite($fp,"Write something here\n");<br />    flock($fp,LOCK_UN);<br />}else{<br />    echo 'Couldn\'t lock the file !';<br />}<br /><p>fclose($fp);</p>

しかし、PHP では flock はそれほどうまく機能しないようです。複数の同時実行の場合、リソースが独占されてすぐに解放されないか、まったく解放されないことが多く、デッドロックが発生し、サーバーの CPU 使用率が非常に高くなり、場合によってはサーバーが完全に停止することもあるようです。これは多くの Linux/UNIX システムで発生するようです。したがって、flock を使用する前に慎重に検討する必要があります。それで解決策はないのでしょうか?

実際にはそうではありません。 flock() を適切に使用すれば、デッドロックの問題を解決することは完全に可能です。もちろん、flock() 関数の使用を考慮しない場合でも、問題に対する適切な解決策はあります。私個人の収集と要約を経て、解決策は大まかに次のようにまとめられます。

オプション 1: ファイルをロックするときにタイムアウトを設定します。大まかな実装は以下の通りです。

<p>if($fp=fopen($fileName,'a')){</p>	$startTime=microtime();<br />	do{<br />		$canWrite=flock($fp,LOCK_EX);<br />		if(!$canWrite){<br />			usleep(round(rand(0,100)*1000));<br />		}<br />	}while((!$canWrite)&&((microtime()-$startTime)<1000));<br />	if($canWrite){<br />		fwrite($fp,$dataToSave);<br />	}<br />	fclose($fp);<br /><p>}</p>

タイムアウトは1msに設定されており、この時間内にロックが取得できなかった場合は、操作権が得られるまで繰り返しロックを取得します。もちろんファイルは取得されます。タイムアウト制限に達した場合は、ただちに終了してロックを放棄し、他のプロセスが動作できるようにする必要があります。

オプション 2: flock 関数を使用せず、一時ファイルを使用して読み取りと書き込みの競合の問題を解決します。一般原則は次のとおりです:

(1) 更新する必要があるファイルのコピーを一時ファイル ディレクトリに置き、ファイルの最終変更時刻を変数に保存し、ランダムな時刻を選択します。この一時ファイルの場合、ファイル名を複製するのは簡単ではありません。

(2) この一時ファイルを更新した後、元のファイルの最終更新時刻が以前に保存した時刻と一致しているかどうかを確認します。

(3) 最終変更時刻が同じ場合、変更された一時ファイルの名前を元のファイルに変更します。ファイルのステータスが同期して更新されるようにするには、ファイルのステータスをクリアする必要があります。

(4) ただし、最終変更時刻が以前に保存された時刻と一致する場合は、この期間中に元のファイルが変更されたことを意味するため、この時点で一時ファイルを削除する必要があります。その後 false を返し、ファイルが現在他のプロセスによって操作されていることを示します。おおよその実装コードは次のとおりです。

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

上記のコードで使用されている関数については、説明が必要です。

(1) rename( ); ファイルまたはディレクトリの名前を変更する関数は、実際には Linux の mv に似ています。ファイルやディレクトリのパスや名前を更新すると便利です。ただし、ウィンドウで上記のコードをテストすると、新しいファイル名がすでに存在する場合、現在のファイルがすでに存在するという通知が表示されます。ただし、Linux では正常に動作します。

(2) clearstatcache(); ファイルのステータスをクリアします。PHP はパフォーマンスを向上させるためにすべてのファイル属性情報をキャッシュしますが、複数のプロセスがファイルを削除または更新するときに、PHP が失敗することがあります。キャッシュ内のファイル属性を更新する時間は、実際のデータではない最終更新時間に簡単にアクセスできます。したがって、ここではこの関数を使用して保存されたキャッシュをクリアする必要があります。

オプション 3: 同時実行の可能性を減らすために、操作されたファイルをランダムに読み書きします。このソリューションは、ユーザーのアクセス ログを記録するときによく使用されるようです。以前は、ランダムなスペースを定義する必要がありましたが、スペースが大きいほど、同時実行の可能性は低くなり、ランダムな読み取りおよび書き込みスペースが [1 ~ 500] であると仮定すると、ログ ファイルの分布範囲は log1 から log500 になります。ユーザーがアクセスするたびに、log1 ~ log500 までの任意のファイルにデータがランダムに書き込まれます。同時に、2 つのプロセスがログを記録しています。プロセス A は更新された log32 ファイルである可能性がありますが、プロセス B はどうなるでしょうか。このときの更新は log399 になる可能性があります。プロセス B にも log32 を実行させたい場合、確率は基本的に 1/500 であり、ほぼゼロに等しいことを知っておく必要があります。アクセスログを分析する必要がある場合、これらのログをマージしてから分析するだけで済みます。このソリューションを使用してログを記録する利点の 1 つは、プロセス操作がキューに入れられる可能性が比較的小さく、プロセスが各操作を非常に迅速に完了できることです。

オプション 4: 操作するすべてのプロセスをキューに入れます。次に、ファイル操作を完了するための専用サービスを配置します。キュー内の除外された各プロセスは最初の特定の操作に相当するため、初めて、サービスはキューから特定の操作アイテムを取得するだけで済みます。ここに多数のファイル操作プロセスがある場合でも、それは問題ではありません。列の後ろに並んでください。列に並ぶ意思がある限り、列の長さは関係ありません。前述のオプションには、それぞれ独自の利点があります。これは大きく 2 つのカテゴリに分類できます:

(1) キューイングが必要 (影響が遅い) (オプション 1、2、および 4 など)

(2) キューイングは必要ありません。 (ファーストインパクト) オプション 3 キャッシュ システムを設計する場合、通常、オプション 3 は使用しません。案3は解析プログラムと書き込みプログラムが同期していないため、書き込みの際に解析の難易度は全く考慮されず、書き込みがよければ問題ありません。想像してみてください。キャッシュの更新時にランダムなファイルの読み書きも併用すると、キャッシュの読み込み時に多くの処理が追加されそうです。ただし、オプション 1 と 2 はまったく異なりますが、書き込み時間はかかりますが (ロックの取得に失敗した場合は繰り返し取得されます)、ファイルの読み取りは非常に便利です。キャッシュを追加する目的は、データ読み取りのボトルネックを軽減し、それによってシステムのパフォーマンスを向上させることです。


声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
unset()とsession_destroy()の違いは何ですか?unset()とsession_destroy()の違いは何ですか?May 04, 2025 am 12:19 AM

thedifferencebetferencefued fieneunset()andsession_destroy()isthatunset()clearsspecificsessionvariablesはsessionactiveであり、ssession_destroy()ターミナテンテンセッション

負荷分散のコンテキストでの粘着性セッション(セッションアフィニティ)とは何ですか?負荷分散のコンテキストでの粘着性セッション(セッションアフィニティ)とは何ですか?May 04, 2025 am 12:16 AM

StickysionsionsureuserRequestsoredtotheSameserverforsessiondataconsistency.1)Sessionidedificationisionidificationsisignivisionsignsignsuserstoserversusing okiesorurlmodifications.2)CondingRoutingDirectSSubSubSubsEntRequestStotheSameserver.3)LoadBalancingDistributeNewuser

PHPで利用可能なさまざまなセッション保存ハンドラーは何ですか?PHPで利用可能なさまざまなセッション保存ハンドラーは何ですか?May 04, 2025 am 12:14 AM

phpoffersvarioussionsionsavehandlers:1)ファイル:デフォルト、simplebutmaybottleneckonhigh-trafficsites.2)memcached:high-performance、yealforspeed-criticalapplications.3)redis:similartomcached、witordededpersistence.4)データベースの提供

PHPでのセッションとは何ですか?なぜそれらが使用されているのですか?PHPでのセッションとは何ですか?なぜそれらが使用されているのですか?May 04, 2025 am 12:12 AM

PHPでのセッションは、サーバー側のユーザーデータを保存して、複数のリクエスト間で状態を維持するメカニズムです。具体的には、1)セッションはsession_start()関数によって開始され、データは保存され、$ _Sessionスーパーグローバルアレイを読みます。 2)セッションデータはデフォルトでサーバーの一時ファイルに保存されますが、データベースまたはメモリストレージを介して最適化できます。 3)セッションを使用して、ユーザーのログインステータス追跡とショッピングカート管理機能を実現できます。 4)セッションの安全な送信とパフォーマンスの最適化に注意を払い、アプリケーションのセキュリティと効率を確保します。

PHPセッションのライフサイクルを説明してください。PHPセッションのライフサイクルを説明してください。May 04, 2025 am 12:04 AM

phpssionsStartWithsession_start()、figenateAuniqueidandcreateSaServerfile; theySistacrossRequestsandcanbemanbemanBeithsession_destroy()

絶対的なセッションタイムアウトとアイドルセッションのタイムアウトの違いは何ですか?絶対的なセッションタイムアウトとアイドルセッションのタイムアウトの違いは何ですか?May 03, 2025 am 12:21 AM

絶対セッションのタイムアウトはセッションの作成時に開始され、アイドルセッションタイムアウトはユーザーの操作なしに開始されます。絶対セッションタイムアウトは、金融アプリケーションなど、セッションライフサイクルの厳格な制御が必要なシナリオに適しています。アイドルセッションタイムアウトは、ソーシャルメディアなど、ユーザーが長い間セッションをアクティブに保つことを望んでいるアプリケーションに適しています。

セッションがサーバーで機能していない場合、どのような措置を講じますか?セッションがサーバーで機能していない場合、どのような措置を講じますか?May 03, 2025 am 12:19 AM

サーバーセッションの障害は、手順に従って解決できます。1。セッションが正しく設定されていることを確認するために、サーバーの構成を確認します。 2.クライアントCookieを確認し、ブラウザがそれをサポートしていることを確認し、正しく送信します。 3. Redisなどのセッションストレージサービスを確認して、それらが正常に動作していることを確認します。 4.アプリケーションコードを確認して、正しいセッションロジックを確認します。これらの手順を通じて、会話の問題を効果的に診断および修復し、ユーザーエクスペリエンスを改善することができます。

session_start()関数の重要性は何ですか?session_start()関数の重要性は何ですか?May 03, 2025 am 12:18 AM

session_start()iscrucialinphpformangingusersions.1)itInitiateSanewsessionifnoneExists、2)resumesanexistingsession、および3)SetSessionCookieforcontinuityAcrossRequests、ApplicationslicationSliviseSlikeUserauthicationAnticatent。

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 中国語クラック版

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

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

mPDF

mPDF

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

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール