加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php文件锁产生的问题和处理方案

发布时间:2022-07-29 14:57:01 所属栏目:PHP教程 来源:互联网
导读:一个真实案例 想起自己之前犯过一个相关的错误。当时场景是这样的:有一个微信公众号项目,调用微信公众号的接口都需要access_token,它的有效期是2小时。当时我的做法是把它存放在文件中,格式使用的是json。{access_token:easWasdw32323, expire:158821906
  一个真实案例
  想起自己之前犯过一个相关的错误。当时场景是这样的:有一个微信公众号项目,调用微信公众号的接口都需要access_token,它的有效期是2小时。当时我的做法是把它存放在文件中,格式使用的是json。{"access_token":"easWasdw32323", "expire":1588219064}。伪代码如下:
 
      } 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));
 
  如何规避这个错误呢?
 
  文件锁机制可以完成。
 
  在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
 
  $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
 
 
  $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才能拿到独占锁,然后才能写入文件。
 
  解决问题
  学完这些知识后,就能解决我之前的问题了。改进的代码如下:
 
 
  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'];    
 
      }
 
 
  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'];
 
  }

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读