전에 관련 실수를 했던 기억이 나네요. 당시 현장은 이렇습니다. 위챗 공개 계정 프로젝트가 있었는데, 위챗 공개 계정을 호출하는 인터페이스에는 access_token
이 필요하고 유효 기간은 2시간입니다. 그때 제가 한 일은 파일로 저장하는 것이었고, 형식은 json
이었습니다. {"access_token":"easWasdw32323", "expire":1588219064}
. 의사 코드는 다음과 같습니다. 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']; }
出现的问题:
项目运行一段时间后就会出问题,但过一两秒后再刷新就正常了。
问题原因分析:
假设token已经过期了,这时候有2个请求来了,分别命名为A、B。A来了,发现token到期后,去调用微信接口获取新的token,获取后,更新到存放token的文件中。
但是,文件没有完全更新完毕的时候,B来了,读入存放token的文件。因为token文件中数据没有更新完整,B读到的数据就会产生错误。
另外还有可能是A和B同时在更新文件内容,这样就会产生数据混乱,也会导致错误发生。
如何规避这个错误呢?
文件锁机制可以完成。
在PHP中提供了 flock()函数,可以对文件使用锁定机制(锁定或释放文件)。当一个进程在访问文件时加上锁,其他进程要想对该文件进行访问,则必须等到锁定被释放以后。这样就可以避免在并发访问同一个文件时破坏数据。
函数原型如下:
flock ( resource $handle , int $operation [, int &$wouldblock ] ) : bool
handle
:
文件系统指针,是典型地由 fopen() 创建的 resource(资源)。
operation
operation 可以是以下值之一:
LOCK_SH取得共享锁定(读取的程序)。
LOCK_EX 取得独占锁定(写入的程序)。
LOCK_UN 释放锁定(无论共享或独占)。
LOCK_NB附加锁定(Windows 上还不支持)。
wouldblock
<?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);
flock (resource $handle , int $Operation [, int &$wouldblock ] ) : bool
🎜handle
: 🎜🎜 파일 시스템 포인터. 일반적으로 fopen()에 의해 생성되는 리소스입니다. 🎜 차단
🎜🎜🎜🎜 잠금이 차단되는 경우(EWOULDBLOCK 오류 코드) 선택적 세 번째 매개변수는 다음과 같습니다. TRUE로 설정합니다. (Windows에서는 지원하지 않습니다.) 🎜🎜demo🎜🎜demo1.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);
<?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 중국어 웹사이트의 기타 관련 기사를 참조하세요!