ホームページ >バックエンド開発 >PHPチュートリアル >PHP ファイルロックによって引き起こされる問題と解決策 (実際のケース)
私は以前に関連する間違いを犯したことを思い出しました。その時の状況は次のとおりです。WeChat パブリック アカウント プロジェクトがあり、WeChat パブリック アカウントを呼び出すためのインターフェイスには access_token
が必要で、その有効期間は 2 時間でした。そのとき私がやったのはファイルに保存することで、形式は json
でした。 {"access_token":"easWasdw32323", "expire":1588219064}
。疑似コードは次のとおりです。
function getToken ($tokenFile) { $tokenJson = file_get_contents($tokenFile); if (!$tokenJson) { $token = loadToken($tokenFile); } else if (json_decode($tokenJson, true)['expire'] <= time()){ $token = loadToken($tokenFile); } else { $token = json_decode($tokenJson, true)['access_token']; } return $token; } function loadToken ($tokenFile) { $fp = fopen($tokenFile, 'r+'); $tokenJson = ...; // 调用微信接口获取到token fwrite($fp, json_encode($tokenJson)); return $tokenJson['access_token']; }
発生する問題:
プロジェクトを一定期間実行すると問題が発生しますが、その後は正常になります。 1 ~ 2 秒後にリフレッシュされます。
問題の原因の分析:
トークンの有効期限が切れたと仮定すると、この時点で、それぞれ A と B という名前の 2 つのリクエストが来ます。 A が来ると、トークンの有効期限が切れた後、WeChat インターフェイスを呼び出して新しいトークンを取得し、取得後、トークンを保存するファイルを更新します。
しかし、ファイルが完全に更新されていないときに、B がトークンを格納したファイルを読みに来ました。トークン ファイル内のデータが完全に更新されていないため、B によって読み取られたデータはエラーを引き起こします。
さらに、A と B がファイルの内容を同時に更新している可能性があり、データの混乱が生じ、エラーが発生する可能性があります。
このエラーを回避するにはどうすればよいですか?
ファイルのロック機構を完成させることができます。
PHP では flock() 関数が提供されており、ファイルのロック メカニズム (ファイルのロックまたは解放) を使用できます。プロセスがファイルにアクセスするときにファイルをロックすると、他のプロセスがそのファイルにアクセスする場合は、ロックが解除されるまで待つ必要があります。これにより、同じファイルへの同時アクセス時のデータ破損が回避されます。
関数のプロトタイプは次のとおりです:
flock ( resource $handle , int $operation [, int &$wouldblock ] ) : bool
handle
:
ファイル システム ポインターは、通常は fopen() によって作成されるリソースです。
## 操作
<?php $file = 'data.txt'; $handler = fopen($file, 'a+') or die('文件资源打开失败'); // 取得独占锁 if (flock($handler, LOCK_EX)) { sleep(5); flock($handler, LOCK_UN); } else { echo '锁定失败'; } fclose($handler);
<?php $file = 'data.txt'; $handler = fopen($file, 'a+') or die('文件资源打开失败'); // 取得独占锁 if (flock($handler, LOCK_EX)) { fwrite($handler, 'sometest string'); flock($handler, LOCK_UN); } else { echo '锁定失败'; } fclose($handler);demo1.php を最初に実行してから、demo2.php を実行します。このファイルは、demo1.php によってロックされているため、demo2.php は新しいコンテンツを書き込むことができません。demo1.php がロックを解放した後でのみ、demo2.php が排他ロックを取得してファイルを書き込むことができます。 問題の解決この知識を学べば、以前の問題を解決できるようになります。改善されたコードは次のとおりです:
<?php function getToken ($tokenFile){ $tokenJson = file_get_contents($tokenFile); if (!$tokenJson) { $token = loadToken($tokenFile); } else if (json_decode($tokenJson, true)['expire'] <= time()){ $token = loadToken($tokenFile); } else { $token = json_decode($tokenJson, true)['access_token']; } return $token; } function loadToken ($tokenFile) { $fp = fopen($tokenFile, 'w'); // 取得独占锁 if (flock($fp, LOCK_EX)) { $tokenJson = ...; // 调用微信接口获取到token fwrite($fp, json_encode($tokenJson)); flock($fp, LOCK_UN); } else { return false; } return $tokenJson['access_token']; }
以上がPHP ファイルロックによって引き起こされる問題と解決策 (実際のケース)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。