php文件锁产生的问题和解决方案(一个真实案例)-php教程

资源魔 34 0

一个实在案例

想起本人以前犯过一个相干的谬误。过后场景是这样的:有一个微信大众号名目,挪用微信大众号的接口都需求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文件锁

抱歉,评论功能暂时关闭!