温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

php文件锁错误案例以及解决方案

发布时间:2020-05-13 09:40:40 来源:亿速云 阅读:189 作者:Leah 栏目:编程语言

本篇文章主要探讨php文件锁发生错误的解决方法。有一定的参考价值,有需要的朋友可以参考一下,跟随小编一起来看解决方法吧。

微信公众号项目调用微信公众号的接口都需要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文件锁发生错误的解决方法的详细内容,代码示例简单明了,如果在日常工作遇到此问题。通过这篇文章,希望你能有所收获,更多详情敬请关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI