Mir fiel ein, dass ich schon einmal einen ähnlichen Fehler gemacht hatte. Die Szene zu dieser Zeit war folgende: Es gab ein Projekt für ein öffentliches WeChat-Konto, und die Schnittstelle zum Aufrufen des öffentlichen WeChat-Kontos war erforderlich access_token
und ihre Gültigkeitsdauer beträgt 2 Stunden. Was ich damals gemacht habe, war, es in einer Datei im Format json
zu speichern. {"access_token":"easWasdw32323", "expire":1588219064}
. Der Pseudocode lautet wie folgt:
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']; }
Probleme:
Das Projekt wird nach einiger Zeit Probleme haben, aber nach einer Aktualisierung nach einer Sekunde oder einer Weile wird es normal sein zwei.
Analyse der Ursache des Problems:
Angenommen, das Token ist abgelaufen. Zu diesem Zeitpunkt kommen zwei Anfragen mit den Namen A und B. Als A kommt, stellt er fest, dass er nach Ablauf des Tokens die WeChat-Schnittstelle aufruft, um ein neues Token zu erhalten. Nachdem er es erhalten hat, aktualisiert er es in der Datei, in der das Token gespeichert ist.
Als die Datei jedoch nicht vollständig aktualisiert wurde, kam B und las die Datei, in der das Token gespeichert war. Da die Daten in der Token-Datei nicht vollständig aktualisiert werden, führen die von B gelesenen Daten zu Fehlern.
Darüber hinaus ist es möglich, dass A und B den Dateiinhalt gleichzeitig aktualisieren, was zu Datenverwirrung und Fehlern führt.
Wie vermeide ich diesen Fehler?
Der Dateisperrmechanismus kann abgeschlossen werden.
Die Funktion flock() wird in PHP bereitgestellt, die den Sperrmechanismus (Datei sperren oder freigeben) für die Datei verwenden kann. Wenn ein Prozess beim Zugriff auf eine Datei eine Datei sperrt, müssen andere Prozesse warten, bis die Sperre aufgehoben wird, wenn sie auf die Datei zugreifen möchten. Dadurch wird eine Datenbeschädigung beim gleichzeitigen Zugriff auf dieselbe Datei vermieden.
Der Funktionsprototyp lautet wie folgt:
flock ( resource $handle , int $operation [, int &$wouldblock ] ) : bool
handle
:
Der Dateisystemzeiger ist normalerweise Wird von fopen() verwendet und erstellte Ressource.
Operation
Operation kann einer der folgenden Werte sein:
LOCK_SH erwirbt die gemeinsame Sperre (Leseprogramm).
wouldblock
demo
<?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);
demo2.php
<?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);
Probleme lösen
Nachdem ich mir dieses Wissen angeeignet habe, werde ich in der Lage sein, meine bisherigen Probleme zu lösen. Der verbesserte Code lautet wie folgt:
<?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']; }
Das obige ist der detaillierte Inhalt vonProbleme und Lösungen, die durch die PHP-Dateisperre verursacht werden (ein realer Fall). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!