一个实在案例
想起本人以前犯过一个相干的谬误。过后场景是这样的:有一个微信大众号名目,挪用微信大众号的接口都需求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
假如锁定会梗塞的话(EWOULDBLOCK 谬误码状况下),可选的第三个参数会被设置为 TRUE。(Windows 上没有支持)
demo
demo1.php
<?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);
先运转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开发教程 php开发资料 php开发自学 php文件锁
抱歉,评论功能暂时关闭!